citrun

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

commit 9b4d8ee92bc8ba0131cf79f2bfbee913c9a03a1b
parent e2fadc1e7900d5788733266795e43334e990fc8e
Author: Kyle Milz <kyle@0x30.net>
Date:   Tue, 10 Jan 2017 00:23:46 -0700

lib: split into os independent parts

Diffstat:
Mlib.c | 215++++---------------------------------------------------------------------------
Alib_os.h | 6++++++
Alib_unix.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib_win32.c | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 270 insertions(+), 205 deletions(-)

diff --git a/lib.c b/lib.c @@ -13,208 +13,20 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef _WIN32 -#include <direct.h> /* getcwd */ -#include <stdio.h> /* stderr */ -#include <windows.h> /* HANDLE, MapViewOfFile, ... */ -#include <io.h> -#define PATH_MAX 32000 - -#define DEFAULT_PROCDIR "C:\\CItRun" -static HANDLE h = INVALID_HANDLE_VALUE; -#else /* _WIN32 */ -#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 <stdio.h> -#include <stdlib.h> /* atexit, get{env,progname} */ -#include <string.h> /* str{l,n}cpy */ -#include <unistd.h> /* lseek get{cwd,pid,ppid,pgrp} */ - -#define DEFAULT_PROCDIR "/tmp/citrun" -static int fd; -#endif /* _WIN32 */ +#include <stdlib.h> /* exit */ +#include <stdio.h> /* fprintf, stderr */ +#include <string.h> /* strncpy */ +#include <unistd.h> /* getcwd */ #include "lib.h" /* citrun_*, struct citrun_{header,node} */ +#include "lib_os.h" /* extend, open_fd */ +static int init; static struct citrun_header *header; -#ifdef _WIN32 -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); -} - -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 - ); -} -#endif /* _WIN32 */ - -static size_t -align_bytes(size_t unaligned_bytes) -{ - size_t page_mask; - -#ifdef _WIN32 - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - - page_mask = system_info.dwAllocationGranularity - 1; -#else - page_mask = getpagesize() - 1; -#endif /* _WIN32 */ - return (unaligned_bytes + page_mask) & ~page_mask; -} - -/* - * 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. - */ -static void * -extend(size_t req_bytes) -{ - size_t aligned_bytes; - size_t len; - void *mem; - - aligned_bytes = align_bytes(req_bytes); - -#ifdef _WIN32 - HANDLE fm; - - /* 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); -#else /* _WIN32 */ - /* 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); -#endif /* _WIN32 */ - - return mem; -} - -static void -get_prog_name(char *buf, size_t buf_size) -{ -#ifdef _WIN32 - if (GetModuleFileName(NULL, buf, buf_size) == 0) - Err(1, "GetModuleFileName"); -#else - strlcpy(buf, getprogname(), buf_size); -#endif -} - -/* - * Opens a file with a random suffix. Exits on error. - */ -static void -open_fd() -{ - char *procdir; - char procfile[PATH_MAX]; - - if ((procdir = getenv("CITRUN_PROCDIR")) == NULL) - procdir = DEFAULT_PROCDIR; - -#ifdef _WIN32 - 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"); -#else /* _WIN32 */ - 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"); -#endif /* _WIN32 */ -} - /* - * Called by atexit(3), which doesn't always get called (this is unreliable). + * Try and set a flag if the atexit() trigger actually fires. */ static void set_exited(void) @@ -235,12 +47,8 @@ add_header() header->major = citrun_major; header->minor = citrun_minor; - header->pids[0] = getpid(); -#ifndef _WIN32 - header->pids[1] = getppid(); - header->pids[2] = getpgrp(); -#endif /* ! _WIN32 */ + get_pids(header->pids); get_prog_name(header->progname, sizeof(header->progname)); if (getcwd(header->cwd, sizeof(header->cwd)) == NULL) @@ -270,13 +78,10 @@ citrun_node_add(unsigned int major, unsigned int minor, struct citrun_node *n) exit(1); } -#ifdef _WIN32 - if (h == INVALID_HANDLE_VALUE) { -#else - if (fd == 0) { -#endif /* _WIN32 */ + if (init == 0) { open_fd(); add_header(); + init = 1; } /* Allocate enough room for node and live execution buffers. */ diff --git a/lib_os.h b/lib_os.h @@ -0,0 +1,6 @@ +/* + * Operating system specific functions. + */ +void *extend(size_t); +void get_prog_name(char *, size_t); +void open_fd(); diff --git a/lib_unix.c b/lib_unix.c @@ -0,0 +1,101 @@ +/* + * 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> /* lseek get{cwd,pid,ppid,pgrp} */ + +#include "lib_os.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. + */ +void * +extend(size_t req_bytes) +{ + size_t aligned_bytes; + size_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; +} + +/* + * Opens a file with a random suffix. Exits on error. + */ +void +open_fd() +{ + char *procdir; + char procfile[PATH_MAX]; + + if ((procdir = getenv("CITRUN_PROCDIR")) == NULL) + procdir = "/tmp/citrun"; + + 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"); +} + +void +get_pids(unsigned int pids[3]) +{ + pids[0] = getpid(); + pids[1] = getppid(); + pids[2] = getpgrp(); +} + +void +get_prog_name(char *buf, size_t buf_size) +{ + strlcpy(buf, getprogname(), buf_size); +} diff --git a/lib_win32.c b/lib_win32.c @@ -0,0 +1,153 @@ +/* + * 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_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 * +extend(size_t req_bytes) +{ + size_t aligned_bytes; + size_t len; + 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; + + HANDLE fm; + + /* 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 +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 +get_prog_name(char *buf, size_t buf_size) +{ + if (GetModuleFileName(NULL, buf, buf_size) == 0) + Err(1, "GetModuleFileName"); +} + +void +get_pids(unsigned int pids[3]) +{ + pids[0] = getpid(); +}