commit b5b211e659abe01734b294a39b6ceeb4786bd77d
parent 3118708119a43d9dd745e8495d8467c368ca5a39
Author: Kyle Milz <krwmilz@gmail.com>
Date: Sun, 25 Mar 2018 11:00:23 -0700
lib: rename files mostly removing lib_ prefix
Diffstat:
14 files changed, 481 insertions(+), 481 deletions(-)
diff --git a/Jamrules b/Jamrules
@@ -137,7 +137,7 @@ actions CCItRunRun
-e "s,citrun_node_add,ccitrunrun_node_add," \
-e "s,citrun_major,ccitrunrun_major,g" \
-e "s,citrun_minor,ccitrunrun_minor,g" \
- lib.h lib.c inst_action.cc inst_fe.cc gl_procfile.cc
+ citrun.h citrun.c inst_action.cc inst_fe.cc gl_procfile.cc
#
# Change binary names so we can do a side by side installation.
@@ -147,7 +147,7 @@ actions CCItRunRun
-e "s,citrun_term,ccitrunrun_term," \
-e "s,citrun_gl,ccitrunrun_gl," \
-e "s,libcitrun,libccitrunrun," \
- Jamfile lib.c inst_main.cc
+ Jamfile citrun.c inst_main.cc
jam
}
diff --git a/bin/gl_runtime.cc b/bin/gl_runtime.cc
@@ -24,7 +24,7 @@
#include <iostream> // std::cerr
#include <sstream> // std::stringstream
-#include "lib.h" // struct citrun_node
+#include "citrun.h" // struct citrun_node
#include "gl_runtime.h" // citrun::gl_transunit, citrun::gl_procfile
diff --git a/bin/inst_action.cc b/bin/inst_action.cc
@@ -14,7 +14,7 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
#include "inst_action.h"
-#include "lib_h.h"
+#include "citrun_h.h" // citrun_h
#include <clang/Frontend/CompilerInstance.h>
#include <fstream>
@@ -73,7 +73,7 @@ R"(#ifdef __cplusplus
extern "C" {
#endif
)";
- preamble << lib_h;
+ preamble << citrun_h;
preamble << "static struct citrun_node _citrun = {\n"
<< " " << num_lines << ",\n"
<< " \"" << m_compiler_file_name << "\",\n"
diff --git a/bin/inst_fe.cc b/bin/inst_fe.cc
@@ -15,7 +15,7 @@
//
#include "inst_action.h" // InstrumentActionFactory
#include "inst_fe.h"
-#include "lib.h" // citrun_major, citrun_minor
+#include "citrun.h" // citrun_major, citrun_minor
#include <clang/Basic/Diagnostic.h> // IgnoringDiagConsumer
#include <clang/Tooling/CommonOptionsParser.h>
diff --git a/lib/Jamfile b/lib/Jamfile
@@ -1,8 +1,8 @@
SubDir TOP lib ;
-Stringize lib_h.h : lib.h ;
+Stringize citrun_h.h : citrun.h ;
-ObjectCcFlags lib.c lib_unix.c : -fPIC -ansi ;
-Library libcitrun : lib.c lib_unix.c ;
+ObjectCcFlags citrun.c unix.c : -fPIC -ansi ;
+Library libcitrun : citrun.c unix.c ;
InstallLib $(PREFIX)/lib : libcitrun.a ;
diff --git a/lib/citrun.c b/lib/citrun.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2016 Kyle Milz <kyle@0x30.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <stdlib.h> /* exit */
+#include <stdio.h> /* fprintf, stderr */
+#include <string.h> /* strncpy */
+
+#include "citrun.h" /* struct citrun_header, struct citrun_node */
+#include "os.h" /* citrun_{extend,os_info,open_fd} */
+
+
+/*
+ * 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(int fd)
+{
+ struct citrun_header *new_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 various runtime information fields. */
+ citrun_os_info(new_header);
+
+ return new_header;
+}
+
+/*
+ * 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.
+ *
+ * Instrumented program will exit nonzero on failure.
+ */
+void
+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) {
+ fprintf(stderr, "libcitrun %i.%i: incompatible version %i.%i.\n"
+ "Try cleaning and rebuilding your project.\n",
+ citrun_major, citrun_minor, major, minor);
+ exit(1);
+ }
+
+ if (header == NULL) {
+ fd = citrun_open_fd();
+ header = citrun_add_header(fd);
+ citrun_start_viewer();
+ }
+
+ /* Allocate enough room for node and live execution buffers. */
+ sz = sizeof(struct citrun_node);
+ sz += n->size * sizeof(unsigned long long);
+ new = citrun_extend(fd, sz);
+
+ /* Increment accumulation fields in header. */
+ header->units++;
+ header->loc += n->size;
+
+ /* Copy these fields from incoming node verbatim. */
+ new->size = n->size;
+ strncpy(new->comp_file_path, n->comp_file_path, CITRUN_PATH_MAX);
+ strncpy(new->abs_file_path, n->abs_file_path, CITRUN_PATH_MAX);
+ new->comp_file_path[CITRUN_PATH_MAX - 1] = '\0';
+ new->abs_file_path[CITRUN_PATH_MAX - 1] = '\0';
+
+ /* Set incoming nodes data pointer to allocated space after struct. */
+ n->data = (unsigned long long *)(new + 1);
+}
diff --git a/lib/lib.h b/lib/citrun.h
diff --git a/lib/lib.c b/lib/lib.c
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2016 Kyle Milz <kyle@0x30.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <stdlib.h> /* exit */
-#include <stdio.h> /* fprintf, stderr */
-#include <string.h> /* strncpy */
-
-#include "lib.h" /* struct citrun_header, struct citrun_node */
-#include "lib_os.h" /* citrun_{extend,os_info,open_fd} */
-
-
-/*
- * 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(int fd)
-{
- struct citrun_header *new_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 various runtime information fields. */
- citrun_os_info(new_header);
-
- return new_header;
-}
-
-/*
- * 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.
- *
- * Instrumented program will exit nonzero on failure.
- */
-void
-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) {
- fprintf(stderr, "libcitrun %i.%i: incompatible version %i.%i.\n"
- "Try cleaning and rebuilding your project.\n",
- citrun_major, citrun_minor, major, minor);
- exit(1);
- }
-
- if (header == NULL) {
- fd = citrun_open_fd();
- header = citrun_add_header(fd);
- citrun_start_viewer();
- }
-
- /* Allocate enough room for node and live execution buffers. */
- sz = sizeof(struct citrun_node);
- sz += n->size * sizeof(unsigned long long);
- new = citrun_extend(fd, sz);
-
- /* Increment accumulation fields in header. */
- header->units++;
- header->loc += n->size;
-
- /* Copy these fields from incoming node verbatim. */
- new->size = n->size;
- strncpy(new->comp_file_path, n->comp_file_path, CITRUN_PATH_MAX);
- strncpy(new->abs_file_path, n->abs_file_path, CITRUN_PATH_MAX);
- new->comp_file_path[CITRUN_PATH_MAX - 1] = '\0';
- new->abs_file_path[CITRUN_PATH_MAX - 1] = '\0';
-
- /* Set incoming nodes data pointer to allocated space after struct. */
- n->data = (unsigned long long *)(new + 1);
-}
diff --git a/lib/lib_unix.c b/lib/lib_unix.c
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2016 Kyle Milz <kyle@0x30.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/mman.h> /* mmap */
-#include <sys/stat.h> /* S_IRUSR, S_IWUSR, mkdir */
-
-#include <assert.h>
-#include <err.h>
-#include <errno.h> /* EEXIST */
-#include <fcntl.h> /* O_CREAT */
-#include <limits.h> /* PATH_MAX */
-#include <stdlib.h> /* get{env,progname} */
-#include <string.h> /* strl{cpy,cat} */
-#include <unistd.h> /* access, execlp, fork, lseek, get* */
-
-#include "lib.h" /* struct citrun_header */
-#include "lib_os.h"
-
-#define UNIX_PROCDIR "/tmp/citrun"
-
-
-/*
- * Implementation of lib_os.h interface for at least:
- * - OpenBSD
- * - Darwin
- * - Linux
- */
-
-/*
- * Rounds up the second argument to a multiple of the system page size, which
- * makes working with mmap nicer.
- *
- * Get the current mapping length, extend it by truncation and then extend the
- * memory mapping.
- *
- * If this function fails the instrumented program will exit nonzero.
- */
-void *
-citrun_extend(int fd, size_t req_bytes)
-{
- size_t aligned_bytes;
- off_t len;
- void *mem;
- size_t page_mask;
-
- page_mask = getpagesize() - 1;
- aligned_bytes = (req_bytes + page_mask) & ~page_mask;
-
- /* Get current file length. */
- if ((len = lseek(fd, 0, SEEK_END)) < 0)
- err(1, "lseek");
-
- /* Increase file length, filling with zeros. */
- if (ftruncate(fd, len + aligned_bytes) < 0)
- err(1, "ftruncate from %lld to %llu", len, len + aligned_bytes);
-
- /* Increase memory mapping length. */
- mem = mmap(NULL, req_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, len);
-
- if (mem == MAP_FAILED)
- err(1, "mmap %zu bytes @ %llu", req_bytes, len);
-
- return mem;
-}
-
-/*
- * If CITRUN_PROCDIR is not set UNIX_PROCDIR is used as a prefix. Attempt to
- * create the prefix but don't error if it already exists.
- *
- * Create a file name by concatenating the program name with a 10 character (man
- * page suggests this amount) random template and pass that to mkstemp(3).
- *
- * If this program fails the instrumented program will exit nonzero.
- */
-int
-citrun_open_fd()
-{
- const char *procdir;
- char procfile[PATH_MAX];
- int fd;
-
- if ((procdir = getenv("CITRUN_PROCDIR")) == NULL)
- procdir = UNIX_PROCDIR;
-
- if (mkdir(procdir, S_IRWXU) && errno != EEXIST)
- err(1, "mkdir '%s'", procdir);
-
- strlcpy(procfile, procdir, PATH_MAX);
- strlcat(procfile, "/", PATH_MAX);
- strlcat(procfile, getprogname(), PATH_MAX);
- strlcat(procfile, "_XXXXXXXXXX", PATH_MAX);
-
- if ((fd = mkstemp(procfile)) < 0)
- err(1, "mkstemp");
-
- return fd;
-}
-
-/*
- * Fills in the following fields:
- * - process id
- * - parent process id
- * - process group
- * - program name
- * - current working directory
- *
- * This function doesn't fail.
- */
-void
-citrun_os_info(struct citrun_header *h)
-{
- h->pids[0] = getpid();
- h->pids[1] = getppid();
- h->pids[2] = getpgrp();
-
- strlcpy(h->progname, getprogname(), sizeof(h->progname));
-
- if (getcwd(h->cwd, sizeof(h->cwd)) == NULL)
- strncpy(h->cwd, "", sizeof(h->cwd));
-}
-
-/*
- * Checks for the global citrun_gl lock file in the directory either given by the
- * CITRUN_PROCDIR environment variable value or UNIX_PROCDIR if CITRUN_PROCDIR
- * doesn't exist.
- *
- * If no lock file exists a new process is forked that tries to exec 'citrun_gl'
- * which must be on the path.
- *
- * The instrumented program exits on failure and returns nothing on success.
- */
-void
-citrun_start_viewer()
-{
- pid_t pid;
- const char *procdir;
- char viewer_file[PATH_MAX];
-
- if ((procdir = getenv("CITRUN_PROCDIR")) == NULL)
- procdir = UNIX_PROCDIR;
-
- strlcpy(viewer_file, procdir, PATH_MAX);
- strlcat(viewer_file, "/", PATH_MAX);
- strlcat(viewer_file, "citrun_gl.lock", PATH_MAX);
-
- if (access(viewer_file, F_OK)) {
- /* If errno was ENOENT then fall through otherwise error. */
- if (errno != ENOENT)
- err(1, "access");
- } else
- /* File already exists, don't create a new viewer. */
- return;
-
- pid = fork();
- if (pid < 0)
- err(1, "fork");
- else if (pid > 0)
- /* In parent process. */
- return;
-
- /*
- * Use a different name than the instrumented program this library is
- * linked to for better diagnostics in error messages.
- */
- setprogname("libcitrun");
-
- /* In child process, exec the viewer. */
- if (execlp("citrun_gl", "citrun_gl", NULL))
- err(1, "exec citrun_gl");
-}
diff --git a/lib/lib_win32.c b/lib/lib_win32.c
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2016 Kyle Milz <kyle@0x30.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <direct.h> /* getcwd */
-#include <stdio.h> /* stderr */
-#include <windows.h> /* HANDLE, MapViewOfFile, ... */
-#include <io.h>
-#define PATH_MAX 32000
-
-#include "lib.h" /* struct citrun_header */
-#include "lib_os.h"
-
-
-static HANDLE h = INVALID_HANDLE_VALUE;
-
-static void
-Err(int code, const char *fmt)
-{
- char buf[256];
-
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL);
-
- fprintf(stderr, "%s: %s", fmt, buf);
- exit(code);
-}
-
-static HANDLE
-mkstemp(char *template)
-{
- int i;
- unsigned int r;
-
- char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
- for (i = strlen(template) - 1; i > 0; --i) {
- if (template[i] != 'X')
- break;
-
- if (rand_s(&r)) {
- fprintf(stderr, "rand failed: %s\n", strerror(errno));
- exit(1);
- }
-
- template[i] = chars[r % (sizeof(chars) - 1)];
- }
-
- return CreateFile(
- template,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- CREATE_NEW,
- 0,
- NULL
- );
-}
-
-/*
- * 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.
- */
-void *
-citrun_extend(size_t req_bytes)
-{
- size_t aligned_bytes;
- size_t len;
- HANDLE fm;
- void *mem;
- size_t page_mask;
-
- SYSTEM_INFO system_info;
- GetSystemInfo(&system_info);
-
- page_mask = system_info.dwAllocationGranularity - 1;
- aligned_bytes = (req_bytes + page_mask) & ~page_mask;
-
- /* Get current file length. */
- if ((len = GetFileSize(h, NULL)) == INVALID_FILE_SIZE)
- Err(1, "GetFileSize");
-
- /* Increase file pointer to new length. */
- if (SetFilePointer(h, len + aligned_bytes, NULL, FILE_BEGIN)
- == INVALID_SET_FILE_POINTER)
- Err(1, "SetFilePointer");
-
- /* Set new length. */
- if (SetEndOfFile(h) == 0)
- Err(1, "SetEndOfFile");
-
- /* Create a new mapping that's used temporarily. */
- if ((fm = CreateFileMapping(h, NULL, PAGE_READWRITE, 0, 0, NULL)) == NULL)
- Err(1, "CreateFileMapping");
-
- /* Create a new memory mapping for the newly extended space. */
- if ((mem = MapViewOfFile(fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, len, req_bytes)) == NULL)
- Err(1, "MapViewOfFile");
-
- CloseHandle(fm);
- return mem;
-}
-
-/*
- * Opens a file with a random suffix. Exits on error.
- */
-void
-citrun_open_fd()
-{
- char *procdir;
- char procfile[PATH_MAX];
-
- if ((procdir = getenv("CITRUN_PROCDIR")) == NULL)
- procdir = "C:\\CItRun";
-
- if (CreateDirectory(procdir, NULL) == 0 &&
- GetLastError() != ERROR_ALREADY_EXISTS)
- Err(1, "CreateDirectory");
-
- strncpy(procfile, procdir, PATH_MAX);
- strncat(procfile, "\\", PATH_MAX);
- strncat(procfile, "program", PATH_MAX);
- strncat(procfile, "_XXXXXXXXXX", PATH_MAX);
-
- if ((h = mkstemp(procfile)) == INVALID_HANDLE_VALUE)
- Err(1, "mkstemp");
-}
-
-void
-citrun_os_info(struct citrun_header *h)
-{
- h->pids[0] = getpid();
-
- if (GetModuleFileName(NULL, h->progname, sizeof(h->progname)) == 0)
- Err(1, "GetModuleFileName");
-
- if (getcwd(h->cwd, sizeof(h->cwd)) == NULL)
- strncpy(h->cwd, "", sizeof(h->cwd));
-}
diff --git a/lib/lib_os.h b/lib/os.h
diff --git a/lib/unix.c b/lib/unix.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2016 Kyle Milz <kyle@0x30.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/mman.h> /* mmap */
+#include <sys/stat.h> /* S_IRUSR, S_IWUSR, mkdir */
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h> /* EEXIST */
+#include <fcntl.h> /* O_CREAT */
+#include <limits.h> /* PATH_MAX */
+#include <stdlib.h> /* get{env,progname} */
+#include <string.h> /* strl{cpy,cat} */
+#include <unistd.h> /* access, execlp, fork, lseek, get* */
+
+#include "citrun.h" /* struct citrun_header */
+#include "os.h"
+
+#define UNIX_PROCDIR "/tmp/citrun"
+
+
+/*
+ * Implementation of os.h interface for at least:
+ * - OpenBSD
+ * - Darwin
+ * - Linux
+ */
+
+/*
+ * Rounds up the second argument to a multiple of the system page size, which
+ * makes working with mmap nicer.
+ *
+ * Get the current mapping length, extend it by truncation and then extend the
+ * memory mapping.
+ *
+ * If this function fails the instrumented program will exit nonzero.
+ */
+void *
+citrun_extend(int fd, size_t req_bytes)
+{
+ size_t aligned_bytes;
+ off_t len;
+ void *mem;
+ size_t page_mask;
+
+ page_mask = getpagesize() - 1;
+ aligned_bytes = (req_bytes + page_mask) & ~page_mask;
+
+ /* Get current file length. */
+ if ((len = lseek(fd, 0, SEEK_END)) < 0)
+ err(1, "lseek");
+
+ /* Increase file length, filling with zeros. */
+ if (ftruncate(fd, len + aligned_bytes) < 0)
+ err(1, "ftruncate from %lld to %llu", len, len + aligned_bytes);
+
+ /* Increase memory mapping length. */
+ mem = mmap(NULL, req_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, len);
+
+ if (mem == MAP_FAILED)
+ err(1, "mmap %zu bytes @ %llu", req_bytes, len);
+
+ return mem;
+}
+
+/*
+ * If CITRUN_PROCDIR is not set UNIX_PROCDIR is used as a prefix. Attempt to
+ * create the prefix but don't error if it already exists.
+ *
+ * Create a file name by concatenating the program name with a 10 character (man
+ * page suggests this amount) random template and pass that to mkstemp(3).
+ *
+ * If this program fails the instrumented program will exit nonzero.
+ */
+int
+citrun_open_fd()
+{
+ const char *procdir;
+ char procfile[PATH_MAX];
+ int fd;
+
+ if ((procdir = getenv("CITRUN_PROCDIR")) == NULL)
+ procdir = UNIX_PROCDIR;
+
+ if (mkdir(procdir, S_IRWXU) && errno != EEXIST)
+ err(1, "mkdir '%s'", procdir);
+
+ strlcpy(procfile, procdir, PATH_MAX);
+ strlcat(procfile, "/", PATH_MAX);
+ strlcat(procfile, getprogname(), PATH_MAX);
+ strlcat(procfile, "_XXXXXXXXXX", PATH_MAX);
+
+ if ((fd = mkstemp(procfile)) < 0)
+ err(1, "mkstemp");
+
+ return fd;
+}
+
+/*
+ * Fills in the following fields:
+ * - process id
+ * - parent process id
+ * - process group
+ * - program name
+ * - current working directory
+ *
+ * This function doesn't fail.
+ */
+void
+citrun_os_info(struct citrun_header *h)
+{
+ h->pids[0] = getpid();
+ h->pids[1] = getppid();
+ h->pids[2] = getpgrp();
+
+ strlcpy(h->progname, getprogname(), sizeof(h->progname));
+
+ if (getcwd(h->cwd, sizeof(h->cwd)) == NULL)
+ strncpy(h->cwd, "", sizeof(h->cwd));
+}
+
+/*
+ * Checks for the global citrun_gl lock file in the directory either given by the
+ * CITRUN_PROCDIR environment variable value or UNIX_PROCDIR if CITRUN_PROCDIR
+ * doesn't exist.
+ *
+ * If no lock file exists a new process is forked that tries to exec 'citrun_gl'
+ * which must be on the path.
+ *
+ * The instrumented program exits on failure and returns nothing on success.
+ */
+void
+citrun_start_viewer()
+{
+ pid_t pid;
+ const char *procdir;
+ char viewer_file[PATH_MAX];
+
+ if ((procdir = getenv("CITRUN_PROCDIR")) == NULL)
+ procdir = UNIX_PROCDIR;
+
+ strlcpy(viewer_file, procdir, PATH_MAX);
+ strlcat(viewer_file, "/", PATH_MAX);
+ strlcat(viewer_file, "citrun_gl.lock", PATH_MAX);
+
+ if (access(viewer_file, F_OK)) {
+ /* If errno was ENOENT then fall through otherwise error. */
+ if (errno != ENOENT)
+ err(1, "access");
+ } else
+ /* File already exists, don't create a new viewer. */
+ return;
+
+ pid = fork();
+ if (pid < 0)
+ err(1, "fork");
+ else if (pid > 0)
+ /* In parent process. */
+ return;
+
+ /*
+ * Use a different name than the instrumented program this library is
+ * linked to for better diagnostics in error messages.
+ */
+ setprogname("libcitrun");
+
+ /* In child process, exec the viewer. */
+ if (execlp("citrun_gl", "citrun_gl", NULL))
+ err(1, "exec citrun_gl");
+}
diff --git a/lib/win32.c b/lib/win32.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2016 Kyle Milz <kyle@0x30.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <direct.h> /* getcwd */
+#include <stdio.h> /* stderr */
+#include <windows.h> /* HANDLE, MapViewOfFile, ... */
+#include <io.h>
+#define PATH_MAX 32000
+
+#include "citrun.h" /* struct citrun_header */
+#include "os.h"
+
+
+static HANDLE h = INVALID_HANDLE_VALUE;
+
+static void
+Err(int code, const char *fmt)
+{
+ char buf[256];
+
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL);
+
+ fprintf(stderr, "%s: %s", fmt, buf);
+ exit(code);
+}
+
+static HANDLE
+mkstemp(char *template)
+{
+ int i;
+ unsigned int r;
+
+ char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ for (i = strlen(template) - 1; i > 0; --i) {
+ if (template[i] != 'X')
+ break;
+
+ if (rand_s(&r)) {
+ fprintf(stderr, "rand failed: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ template[i] = chars[r % (sizeof(chars) - 1)];
+ }
+
+ return CreateFile(
+ template,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_NEW,
+ 0,
+ NULL
+ );
+}
+
+/*
+ * 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.
+ */
+void *
+citrun_extend(size_t req_bytes)
+{
+ size_t aligned_bytes;
+ size_t len;
+ HANDLE fm;
+ void *mem;
+ size_t page_mask;
+
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+
+ page_mask = system_info.dwAllocationGranularity - 1;
+ aligned_bytes = (req_bytes + page_mask) & ~page_mask;
+
+ /* Get current file length. */
+ if ((len = GetFileSize(h, NULL)) == INVALID_FILE_SIZE)
+ Err(1, "GetFileSize");
+
+ /* Increase file pointer to new length. */
+ if (SetFilePointer(h, len + aligned_bytes, NULL, FILE_BEGIN)
+ == INVALID_SET_FILE_POINTER)
+ Err(1, "SetFilePointer");
+
+ /* Set new length. */
+ if (SetEndOfFile(h) == 0)
+ Err(1, "SetEndOfFile");
+
+ /* Create a new mapping that's used temporarily. */
+ if ((fm = CreateFileMapping(h, NULL, PAGE_READWRITE, 0, 0, NULL)) == NULL)
+ Err(1, "CreateFileMapping");
+
+ /* Create a new memory mapping for the newly extended space. */
+ if ((mem = MapViewOfFile(fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, len, req_bytes)) == NULL)
+ Err(1, "MapViewOfFile");
+
+ CloseHandle(fm);
+ return mem;
+}
+
+/*
+ * Opens a file with a random suffix. Exits on error.
+ */
+void
+citrun_open_fd()
+{
+ char *procdir;
+ char procfile[PATH_MAX];
+
+ if ((procdir = getenv("CITRUN_PROCDIR")) == NULL)
+ procdir = "C:\\CItRun";
+
+ if (CreateDirectory(procdir, NULL) == 0 &&
+ GetLastError() != ERROR_ALREADY_EXISTS)
+ Err(1, "CreateDirectory");
+
+ strncpy(procfile, procdir, PATH_MAX);
+ strncat(procfile, "\\", PATH_MAX);
+ strncat(procfile, "program", PATH_MAX);
+ strncat(procfile, "_XXXXXXXXXX", PATH_MAX);
+
+ if ((h = mkstemp(procfile)) == INVALID_HANDLE_VALUE)
+ Err(1, "mkstemp");
+}
+
+void
+citrun_os_info(struct citrun_header *h)
+{
+ h->pids[0] = getpid();
+
+ if (GetModuleFileName(NULL, h->progname, sizeof(h->progname)) == 0)
+ Err(1, "GetModuleFileName");
+
+ if (getcwd(h->cwd, sizeof(h->cwd)) == NULL)
+ strncpy(h->cwd, "", sizeof(h->cwd));
+}
diff --git a/t/mem.pm b/t/mem.pm
@@ -32,7 +32,7 @@ sub new {
my $node_start = get_aligned_size($header_size);
while ($node_start < $self->{size}) {
- # Struct field ordering controlled by lib.h.
+ # Struct field ordering controlled by citrun.h.
my $data = substr($self->{mem}, $node_start, $node_fixed_size);
my @struct_fields = unpack("IZ256Z256", $data);
@@ -73,7 +73,7 @@ sub get_buffers {
1;
__DATA__
__C__
-#include "../lib/lib.h"
+#include "../lib/citrun.h"
size_t citrun_header_size() {
return sizeof(struct citrun_header);