memzap

replay memory writes
git clone git://git.2f30.org/memzap
Log | Files | Refs | README | LICENSE

commit e654163a70de4946608ce436cb170e3549bdcfd5
parent d373a2f9a9542fa8b6b25be16c70eff6d03bccf7
Author: sin <sin@2f30.org>
Date:   Sun,  3 Mar 2013 00:43:45 +0000

mdiff: Initial commit

Implement the file parsing routines for the mdiff file format.
This code has *not* been tested at all so far.

Diffstat:
MMakefile | 2+-
MMakefile.linux | 2+-
MMakefile.openbsd | 2+-
Amdiff.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mproto.h | 25+++++++++++++++++++++++++
5 files changed, 132 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,6 +1,6 @@ BIN = memzap VER = 0.1 -SRC = memzap.c mem.c utils.c md5.c linux_ops.c +SRC = memzap.c mem.c utils.c md5.c mdiff.c linux_ops.c OBJ = ${SRC:.c=.o} PREFIX = /usr diff --git a/Makefile.linux b/Makefile.linux @@ -1,6 +1,6 @@ BIN = memzap VER = 0.1 -SRC = memzap.c mem.c utils.c md5.c linux_ops.c +SRC = memzap.c mem.c utils.c md5.c mdiff.c linux_ops.c OBJ = ${SRC:.c=.o} PREFIX = /usr diff --git a/Makefile.openbsd b/Makefile.openbsd @@ -1,6 +1,6 @@ BIN = memzap VER = 0.1 -SRC = memzap.c mem.c utils.c md5.c openbsd_ops.c +SRC = memzap.c mem.c utils.c md5.c mdiff.c openbsd_ops.c OBJ = ${SRC:.c=.o} PREFIX = /usr diff --git a/mdiff.c b/mdiff.c @@ -0,0 +1,104 @@ +#include "proto.h" + +int +open_mdiff(const char *path) +{ + int fd; + + fd = open(path, O_RDONLY); + if (fd < 0) + errx(1, "%s: %s", path, strerror(errno)); + return fd; +} + +int +create_mdiff(const char *path) +{ + int fd; + + fd = open(path, O_RDWR); + if (fd < 0) + errx(1, "%s: %s", path, strerror(errno)); + return fd; +} + +int +close_mdiff(int fd) +{ + int ret; + + if (fd < 0) + return -EINVAL; + + ret = close(fd); + if (ret < 0) + err(1, "close"); + return 0; +} + +int +parse_mdiff_hdr(int fd) +{ + struct mdiff_hdr hdr; + ssize_t ret; + + if (fd < 0) + return -EINVAL; + + ret = read(fd, &hdr, sizeof(hdr)); + if (ret != sizeof(hdr)) + err(1, "read"); + if (memcmp(hdr.magic, "MDIFF", sizeof(hdr.magic))) + return -EINVAL; + if (!hdr.nregions) + return -EINVAL; + return 0; +} + +int +mdiff_insert_hdr(int fd, struct mdiff_hdr *hdr) +{ + int ret; + + if (fd < 0 || !hdr) + return -EINVAL; + + ret = lseek(fd, 0, SEEK_SET); + if (ret < 0) + err(1, "lseek"); + ret = write(fd, hdr, sizeof(*hdr)); + if (ret != sizeof(*hdr)) + err(1, "write"); + return 0; +} + +int +mdiff_append_rdiff(int fd, struct mem_region_diff *rdiff) +{ + struct mem_diff *md; + struct mdiff_region mdiff; + size_t i; + ssize_t ret; + + if (fd < 0 || !rdiff) + return -EINVAL; + + /* If this is an empty memory region diff, just bail out */ + if (!rdiff->nmrdiffs) + return 0; + + for (i = 0; i < rdiff->nmrdiffs; i++) { + md = &rdiff->mrdiffs[i]; + mdiff.offset = md->offset; + mdiff.len = md->len; + /* TODO: Handle endianness issues here */ + ret = write(fd, &mdiff, sizeof(mdiff)); + if (ret != sizeof(mdiff)) + err(1, "write"); + ret = write(fd, md->buf, md->len); + if (ret != (ssize_t)md->len) + err(1, "write"); + } + + return 0; +} diff --git a/proto.h b/proto.h @@ -100,6 +100,23 @@ struct mem_tree_entry { }; RB_HEAD(mem_tree, mem_tree_entry); +struct mdiff_hdr { + /* MDIFF\0 */ + char magic[6]; + /* Number of memory diff regions */ + uint32_t nregions; +}; + +struct mdiff_region { + /* Offset into memory where this region should + * be written to */ + uint32_t offset; + /* Length of this memory diff region */ + uint32_t len; + /* Actual data */ + char buf[]; +}; + /* Return the number of blocks in a buffer of `len' bytes */ static inline size_t num_blocks(size_t len) @@ -138,4 +155,12 @@ int traceme(void); int single_step(pid_t pid); void readmem(pid_t pid, void *buf, void *offset, size_t size); +/* mdiff.c */ +int open_mdiff(const char *path); +int create_mdiff(const char *path); +int close_mdiff(int fd); +int parse_mdiff_hdr(int fd); +int mdiff_insert_hdr(int fd, struct mdiff_hdr *hdr); +int mdiff_append_rdiff(int fd, struct mem_region_diff *rdiff); + #endif