From 75f9922f6d3c1e5bbbe7b90ca170392cc0f5efbc Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Sun, 21 Oct 2018 16:23:23 +0300 Subject: Refactor io utils, add *-address-rw tools Namespace io_ stuff into mem_io_ to be less likely to collision with anything else. Add io-stream utility for working with streams instead of direct buffers. Add address-rw tools for simple memory read/write, where regions aren't needed. --- src/cli/cli.h | 12 ++++++ src/cli/proc-address-rw.c | 77 +++++++++++++++++++++++++++++++++++++++ src/cli/proc-region-rw.c | 93 ++++++++++++++++++++++------------------------- src/cli/proc-region-rw.h | 9 ----- src/io/io-ptrace.c | 82 ----------------------------------------- src/io/io-uio.c | 41 --------------------- src/io/io.h | 27 -------------- src/mem/io-ptrace.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ src/mem/io-stream.c | 53 +++++++++++++++++++++++++++ src/mem/io-stream.h | 27 ++++++++++++++ src/mem/io-uio.c | 41 +++++++++++++++++++++ src/mem/io.h | 30 +++++++++++++++ src/ptrace-address-rw.c | 12 ++++++ src/ptrace-region-rw.c | 6 +-- src/uio-address-rw.c | 13 +++++++ src/uio-region-rw.c | 6 +-- src/util.h | 12 ++++++ 17 files changed, 413 insertions(+), 215 deletions(-) create mode 100644 src/cli/cli.h create mode 100644 src/cli/proc-address-rw.c delete mode 100644 src/cli/proc-region-rw.h delete mode 100644 src/io/io-ptrace.c delete mode 100644 src/io/io-uio.c delete mode 100644 src/io/io.h create mode 100644 src/mem/io-ptrace.c create mode 100644 src/mem/io-stream.c create mode 100644 src/mem/io-stream.h create mode 100644 src/mem/io-uio.c create mode 100644 src/mem/io.h create mode 100644 src/ptrace-address-rw.c create mode 100644 src/uio-address-rw.c (limited to 'src') diff --git a/src/cli/cli.h b/src/cli/cli.h new file mode 100644 index 0000000..6262304 --- /dev/null +++ b/src/cli/cli.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include // pid_t + +struct mem_io; + +int +proc_address_rw(int argc, const char *argv[], bool (*)(struct mem_io*, const pid_t)); + +int +proc_region_rw(int argc, const char *argv[], bool (*)(struct mem_io*, const pid_t)); diff --git a/src/cli/proc-address-rw.c b/src/cli/proc-address-rw.c new file mode 100644 index 0000000..6318795 --- /dev/null +++ b/src/cli/proc-address-rw.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include "mem/io.h" +#include "mem/io-stream.h" +#include "util.h" + +static void +usage(const char *argv0) +{ + fprintf(stderr, "usage: %s pid write offset [len] < data\n" + " %s pid read offset len\n", argv0, argv0); + exit(EXIT_FAILURE); +} + +struct options { + size_t offset, len; + enum { + MODE_WRITE, + MODE_READ + } mode; + bool has_len; +}; + +static inline void +options_init(struct options *opt, size_t argc, const char *argv[]) +{ + size_t arg = 0; + *opt = (struct options){0}; + + { + bool w = false, r = false; + const char *mode = argv[arg++]; + if (!(w = !strcmp(mode, "write")) && !(r = !strcmp(mode, "read"))) + errx(EXIT_FAILURE, "mode must be write or read"); + + opt->mode = (w ? MODE_WRITE : MODE_READ); + } + + opt->offset = hexdecstrtoull(argv[arg++], NULL); + + if (argc >= arg + 1) { + opt->len = hexdecstrtoull(argv[arg++], NULL); + opt->has_len = true; + } + + if (opt->mode == MODE_READ && !opt->has_len) + usage(argv[0]); +} + +int +proc_address_rw(int argc, const char *argv[], bool (*mem_io_init)(struct mem_io*, const pid_t)) +{ + if (argc < 4) + usage(argv[0]); + + const pid_t pid = strtoull(argv[1], NULL, 10); + + struct options opt; + options_init(&opt, argc - 2, argv + 2); + + struct mem_io io; + if (!mem_io_init(&io, pid)) + return EXIT_FAILURE; + + size_t trw = 0; + if (opt.mode == MODE_WRITE) { + struct mem_io_istream stream = mem_io_istream_from_file(stdin); + trw = mem_io_write_from_stream(&io, &stream, opt.offset, (opt.has_len ? opt.len : (size_t)~0)); + } else { + struct mem_io_ostream stream = mem_io_ostream_from_file(stdout); + trw = mem_io_read_to_stream(&io, &stream, opt.offset, opt.len); + } + + mem_io_release(&io); + return trw; +} diff --git a/src/cli/proc-region-rw.c b/src/cli/proc-region-rw.c index 5dedf7c..360f7ac 100644 --- a/src/cli/proc-region-rw.c +++ b/src/cli/proc-region-rw.c @@ -1,31 +1,25 @@ #include #include #include -#include "io/io.h" +#include "mem/io.h" +#include "mem/io-stream.h" #include "util.h" static void usage(const char *argv0) { - fprintf(stderr, "usage: %s pid map file [offset] [len] < regions\n" - " %s pid write file [offset] [len] < regions\n" - " %s pid read [offset] [len] < regions\n" + fprintf(stderr, "usage: %s pid map regions data [offset] [len]\n" + " %s pid write regions data [offset] [len]\n" + " %s pid read regions [offset] [len]\n" " regions must be in /proc//maps format", argv0, argv0, argv0); exit(EXIT_FAILURE); } struct context { - void *buf; - struct { size_t offset, len; bool has_offset, has_len; - struct { - FILE *src; - size_t size; - } wm; // write/map - enum { MODE_MAP, MODE_WRITE, @@ -33,7 +27,9 @@ struct context { } mode; } op; - struct io io; + struct mem_io io; + FILE *regions, *data; + size_t data_len, trw; }; static inline void @@ -46,47 +42,47 @@ context_init(struct context *ctx, size_t argc, const char *argv[]) bool m = false, w = false, r = false; const char *mode = argv[arg++]; if (!(m = !strcmp(mode, "map")) && !(w = !strcmp(mode, "write")) && !(r = !strcmp(mode, "read"))) - errx(EXIT_FAILURE, "mode must be write or read"); + errx(EXIT_FAILURE, "mode must be map, write or read"); ctx->op.mode = (m ? MODE_MAP : (w ? MODE_WRITE : MODE_READ)); } - const char *wmname = NULL; - if (ctx->op.mode == MODE_MAP || ctx->op.mode == MODE_WRITE) { - if (argc < arg + 1) - usage(argv[0]); + const char *regions_fname = argv[arg++], *data_fname = NULL; - wmname = argv[arg++]; - } + if (ctx->op.mode != MODE_READ && argc >= arg + 1) + data_fname = argv[arg++]; if (argc >= arg + 1) { - ctx->op.offset = strtoull(argv[arg++], NULL, 10); + ctx->op.offset = hexdecstrtoull(argv[arg++], NULL); ctx->op.has_offset = true; } if (argc >= arg + 1) { - ctx->op.len = strtoull(argv[arg++], NULL, 10); + ctx->op.len = hexdecstrtoull(argv[arg++], NULL); ctx->op.has_len = true; } - if (wmname) { - if (!(ctx->op.wm.src = fopen(wmname, "rb"))) - err(EXIT_FAILURE, "fopen(%s)", wmname); + if (!(ctx->regions = fopen(regions_fname, "rb"))) + err(EXIT_FAILURE, "fopen(%s)", regions_fname); + + if (data_fname) { + if (!(ctx->data = fopen(data_fname, "rb"))) + err(EXIT_FAILURE, "fopen(%s)", data_fname); - if (fseek(ctx->op.wm.src, 0, SEEK_END) != 0) + if (fseek(ctx->data, 0, SEEK_END) != 0) err(EXIT_FAILURE, "fseek"); - ctx->op.wm.size = ftell(ctx->op.wm.src); + ctx->data_len = ftell(ctx->data); } } static void context_release(struct context *ctx) { - if (ctx->op.wm.src) - fclose(ctx->op.wm.src); - - free(ctx->buf); + if (ctx->regions) + fclose(ctx->regions); + if (ctx->data) + fclose(ctx->data); *ctx = (struct context){0}; } @@ -101,32 +97,28 @@ region_cb(const char *line, void *data) warnx("%s", line); region.start += ctx->op.offset; + region.offset *= (ctx->op.mode == MODE_MAP); if (region.start > region.end) { warnx("write offset 0x%zx is out of bounds", region.start); return; } - region.offset = (ctx->op.mode == MODE_MAP ? region.offset : 0); - // requested write/read - const size_t rlen = (ctx->op.has_len ? ctx->op.len : (ctx->op.mode == MODE_READ ? region.end - region.start : ctx->op.wm.size)); - + const size_t rlen = (ctx->op.has_len ? ctx->op.len : (ctx->op.mode == MODE_READ ? region.end - region.start : ctx->data_len)); // actual write/read const size_t len = (rlen > region.end - region.start ? region.end - region.start : rlen); if (!len) return; - if (!(ctx->buf = realloc(ctx->buf, len))) - err(EXIT_FAILURE, "realloc"); - if (ctx->op.mode == MODE_MAP || ctx->op.mode == MODE_WRITE) { - if (fseek(ctx->op.wm.src, region.offset, SEEK_SET) != 0) + if (fseek(ctx->data, region.offset, SEEK_SET) != 0) err(EXIT_FAILURE, "fseek"); - const size_t rd = fread(ctx->buf, 1, len, ctx->op.wm.src); - const size_t wd = ctx->io.write(&ctx->io, ctx->buf, region.start, rd); + struct mem_io_istream stream = mem_io_istream_from_file(ctx->data); + const size_t wd = mem_io_write_from_stream(&ctx->io, &stream, region.start, len); + ctx->trw += wd; if (ctx->op.mode == MODE_WRITE) { if (rlen > wd) { @@ -142,28 +134,29 @@ region_cb(const char *line, void *data) } } } else { - const size_t rd = ctx->io.read(&ctx->io, ctx->buf, region.start, len); - - if (fwrite(ctx->buf, 1, rd, stdout) != rd) - err(EXIT_FAILURE, "fwrite"); + struct mem_io_ostream stream = mem_io_ostream_from_file(stdout); + ctx->trw += mem_io_read_to_stream(&ctx->io, &stream, region.start, len); } } int -proc_region_rw(int argc, const char *argv[], bool (*io_init)(struct io*, const pid_t)) +proc_region_rw(int argc, const char *argv[], bool (*mem_io_init)(struct mem_io*, const pid_t)) { - if (argc < 3) + if (argc < 4) usage(argv[0]); const pid_t pid = strtoull(argv[1], NULL, 10); + struct context ctx; context_init(&ctx, argc - 2, argv + 2); - if (!io_init(&ctx.io, pid)) + if (!mem_io_init(&ctx.io, pid)) return EXIT_FAILURE; - for_each_line_in_file(stdin, region_cb, &ctx); - io_release(&ctx.io); + for_each_line_in_file(ctx.regions, region_cb, &ctx); + const size_t trw = ctx.trw; + + mem_io_release(&ctx.io); context_release(&ctx); - return EXIT_SUCCESS; + return trw; } diff --git a/src/cli/proc-region-rw.h b/src/cli/proc-region-rw.h deleted file mode 100644 index 7ebae67..0000000 --- a/src/cli/proc-region-rw.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include -#include // pid_t - -struct io; - -int -proc_region_rw(int argc, const char *argv[], bool (*io_init)(struct io*, const pid_t)); diff --git a/src/io/io-ptrace.c b/src/io/io-ptrace.c deleted file mode 100644 index 50d0766..0000000 --- a/src/io/io-ptrace.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "io.h" -#include -#include -#include -#include - -static size_t -io_ptrace_do(const struct io *io, void *ptr, const size_t offset, const size_t size, size_t (*iofun)(void*, size_t, size_t, FILE*)) -{ - if (fseek(io->backing, offset, SEEK_SET) != 0) { - warn("fseek(/proc/%u/mem, %zu)", io->pid, offset); - return 0; - } - - return iofun(ptr, 1, size, io->backing); -} - -static size_t -io_ptrace_write(const struct io *io, const void *ptr, const size_t offset, const size_t size) -{ - clearerr(io->backing); - const size_t ret = io_ptrace_do(io, (void*)ptr, offset, size, (size_t(*)())fwrite); - - if (ferror(io->backing)) - warn("fwrite(/proc/%u/mem)", io->pid); - - return ret; -} - -static size_t -io_ptrace_read(const struct io *io, void *ptr, const size_t offset, const size_t size) -{ - clearerr(io->backing); - const size_t ret = io_ptrace_do(io, ptr, offset, size, fread); - - if (ferror(io->backing)) - warn("fread(/proc/%u/mem)", io->pid); - - return ret; -} - -static void -io_ptrace_cleanup(struct io *io) -{ - if (io->backing) - fclose(io->backing); - - if (io->pid) - ptrace(PTRACE_DETACH, io->pid, 1, 0); -} - -bool -io_ptrace_init(struct io *io, const pid_t pid) -{ - *io = (struct io){ .pid = pid, .read = io_ptrace_read, .write = io_ptrace_write, .cleanup = io_ptrace_cleanup }; - - if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1L) { - warn("ptrace(PTRACE_ATTACH, %u, NULL, NULL)", pid); - goto fail; - } - - { - int status; - if (waitpid(pid, &status, 0) == -1 || !WIFSTOPPED(status)) { - warn("waitpid(%u) == %d", pid, status); - goto fail; - } - } - - char path[128]; - snprintf(path, sizeof(path), "/proc/%u/mem", pid); - if (!(io->backing = fopen(path, "w+b"))) { - warn("fopen(%s)", path); - goto fail; - } - - return true; - -fail: - io->cleanup(io); - return false; -} diff --git a/src/io/io-uio.c b/src/io/io-uio.c deleted file mode 100644 index dd9f873..0000000 --- a/src/io/io-uio.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "io.h" -#include -#include -#include - -static size_t -io_uio_do(const struct io *io, const void *ptr, const size_t offset, const size_t size, ssize_t (*iofun)(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)) -{ - const struct iovec lio = { .iov_base = (void*)ptr, .iov_len = size }; - const struct iovec rio = { .iov_base = (void*)(intptr_t)offset, .iov_len = size }; - return iofun(io->pid, &lio, 1, &rio, 1, 0); -} - -static size_t -io_uio_write(const struct io *io, const void *ptr, const size_t offset, const size_t size) -{ - const size_t ret = io_uio_do(io, ptr, offset, size, process_vm_writev); - - if (ret == (size_t)-1) - warn("process_vm_writev(%u)", io->pid); - - return (ret == (size_t)-1 ? 0 : ret); -} - -static size_t -io_uio_read(const struct io *io, void *ptr, const size_t offset, const size_t size) -{ - const size_t ret = io_uio_do(io, ptr, offset, size, process_vm_readv); - - if (ret == (size_t)-1) - warn("process_vm_readv(%u)", io->pid); - - return (ret == (size_t)-1 ? 0 : ret); -} - -bool -io_uio_init(struct io *io, const pid_t pid) -{ - *io = (struct io){ .pid = pid, .read = io_uio_read, .write = io_uio_write }; - return true; -} diff --git a/src/io/io.h b/src/io/io.h deleted file mode 100644 index 8a0639b..0000000 --- a/src/io/io.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include -#include // pid_t - -struct io { - void *backing; - size_t (*read)(const struct io *io, void *ptr, const size_t offset, const size_t size); - size_t (*write)(const struct io *io, const void *ptr, const size_t offset, const size_t size); - void (*cleanup)(struct io *io); - pid_t pid; -}; - -static inline void -io_release(struct io *io) -{ - if (io->cleanup) - io->cleanup(io); - *io = (struct io){0}; -} - -bool -io_uio_init(struct io *io, const pid_t pid); - -bool -io_ptrace_init(struct io *io, const pid_t pid); diff --git a/src/mem/io-ptrace.c b/src/mem/io-ptrace.c new file mode 100644 index 0000000..cf9a861 --- /dev/null +++ b/src/mem/io-ptrace.c @@ -0,0 +1,87 @@ +#include "io.h" +#include +#include +#include +#include + +static size_t +mem_io_ptrace_do(const struct mem_io *io, void *ptr, const size_t offset, const size_t size, size_t (*iofun)(void*, size_t, size_t, FILE*)) +{ + if (fseek(io->backing, offset, SEEK_SET) != 0) { + warn("fseek(/proc/%u/mem, %zu)", io->pid, offset); + return 0; + } + + return iofun(ptr, 1, size, io->backing); +} + +static size_t +mem_io_ptrace_write(const struct mem_io *io, const void *ptr, const size_t offset, const size_t size) +{ + clearerr(io->backing); + const size_t ret = mem_io_ptrace_do(io, (void*)ptr, offset, size, (size_t(*)())fwrite); + + if (ferror(io->backing)) + warn("fwrite(/proc/%u/mem)", io->pid); + + return ret; +} + +static size_t +mem_io_ptrace_read(const struct mem_io *io, void *ptr, const size_t offset, const size_t size) +{ + clearerr(io->backing); + const size_t ret = mem_io_ptrace_do(io, ptr, offset, size, fread); + + if (ferror(io->backing)) + warn("fread(/proc/%u/mem)", io->pid); + + return ret; +} + +static void +mem_io_ptrace_cleanup(struct mem_io *io) +{ + if (io->backing) + fclose(io->backing); + + if (io->pid) + ptrace(PTRACE_DETACH, io->pid, 1, 0); +} + +bool +mem_io_ptrace_init(struct mem_io *io, const pid_t pid) +{ + *io = (struct mem_io){ + .pid = pid, + .read = mem_io_ptrace_read, + .write = mem_io_ptrace_write, + .cleanup = mem_io_ptrace_cleanup + }; + + if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1L) { + warn("ptrace(PTRACE_ATTACH, %u, NULL, NULL)", pid); + goto fail; + } + + { + int status; + if (waitpid(pid, &status, 0) == -1 || !WIFSTOPPED(status)) { + warn("waitpid(%u) == %d", pid, status); + goto fail; + } + } + + char path[128]; + snprintf(path, sizeof(path), "/proc/%u/mem", pid); + if (!(io->backing = fopen(path, "w+b"))) { + warn("fopen(%s)", path); + goto fail; + } + + return true; + +fail: + io->cleanup(io); + return false; +} diff --git a/src/mem/io-stream.c b/src/mem/io-stream.c new file mode 100644 index 0000000..f7c7834 --- /dev/null +++ b/src/mem/io-stream.c @@ -0,0 +1,53 @@ +#include +#include "io-stream.h" +#include "io.h" + +static size_t +file_istream_read(const struct mem_io_istream *stream, void *ptr, const size_t size) +{ + return fread(ptr, 1, size, stream->backing); +} + +struct mem_io_istream +mem_io_istream_from_file(FILE *file) +{ + return (struct mem_io_istream){ + .read = file_istream_read, + .backing = file + }; +} + +size_t +mem_io_write_from_stream(const struct mem_io *io, const struct mem_io_istream *stream, const size_t offset, const size_t size) +{ + size_t trw = 0; + unsigned char buf[4096]; + for (size_t rd, trd = 0; (rd = stream->read(stream, buf, (trd + sizeof(buf) > size ? size - trd : sizeof(buf)))) && trd < size; trd += rd) + trw += io->write(io, buf, offset + trd, rd); + return trw; +} + +static size_t +file_ostream_write(const struct mem_io_ostream *stream, const void *ptr, const size_t size) +{ + return fwrite(ptr, 1, size, stream->backing); +} + +struct mem_io_ostream +mem_io_ostream_from_file(FILE *file) +{ + return (struct mem_io_ostream){ + .write = file_ostream_write, + .backing = file + }; +} + +size_t +mem_io_read_to_stream(const struct mem_io *io, const struct mem_io_ostream *stream, const size_t offset, const size_t size) +{ + size_t trw = 0; + unsigned char buf[4096]; + for (size_t rd, trd = 0; (rd = io->read(io, buf, offset + trd, (trd + sizeof(buf) > size ? size - trd : sizeof(buf)))) && trd < size; trd += rd) + trw += stream->write(stream, buf, rd); + return trw; +} diff --git a/src/mem/io-stream.h b/src/mem/io-stream.h new file mode 100644 index 0000000..ba3b620 --- /dev/null +++ b/src/mem/io-stream.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +struct mem_io; + +struct mem_io_istream { + size_t (*read)(const struct mem_io_istream *stream, void *ptr, const size_t size); + void *backing; +}; + +struct mem_io_istream +mem_io_istream_from_file(FILE *file); + +size_t +mem_io_write_from_stream(const struct mem_io *io, const struct mem_io_istream *stream, const size_t offset, const size_t size); + +struct mem_io_ostream { + size_t (*write)(const struct mem_io_ostream *stream, const void *ptr, const size_t size); + void *backing; +}; + +struct mem_io_ostream +mem_io_ostream_from_file(FILE *file); + +size_t +mem_io_read_to_stream(const struct mem_io *io, const struct mem_io_ostream *stream, const size_t offset, const size_t size); diff --git a/src/mem/io-uio.c b/src/mem/io-uio.c new file mode 100644 index 0000000..c649a45 --- /dev/null +++ b/src/mem/io-uio.c @@ -0,0 +1,41 @@ +#include "io.h" +#include +#include +#include + +static size_t +mem_io_uio_do(const struct mem_io *io, const void *ptr, const size_t offset, const size_t size, ssize_t (*iofun)(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)) +{ + const struct iovec lio = { .iov_base = (void*)ptr, .iov_len = size }; + const struct iovec rio = { .iov_base = (void*)(intptr_t)offset, .iov_len = size }; + return iofun(io->pid, &lio, 1, &rio, 1, 0); +} + +static size_t +mem_io_uio_write(const struct mem_io *io, const void *ptr, const size_t offset, const size_t size) +{ + const size_t ret = mem_io_uio_do(io, ptr, offset, size, process_vm_writev); + + if (ret == (size_t)-1) + warn("process_vm_writev(%u)", io->pid); + + return (ret == (size_t)-1 ? 0 : ret); +} + +static size_t +mem_io_uio_read(const struct mem_io *io, void *ptr, const size_t offset, const size_t size) +{ + const size_t ret = mem_io_uio_do(io, ptr, offset, size, process_vm_readv); + + if (ret == (size_t)-1) + warn("process_vm_readv(%u)", io->pid); + + return (ret == (size_t)-1 ? 0 : ret); +} + +bool +mem_io_uio_init(struct mem_io *io, const pid_t pid) +{ + *io = (struct mem_io){ .pid = pid, .read = mem_io_uio_read, .write = mem_io_uio_write }; + return true; +} diff --git a/src/mem/io.h b/src/mem/io.h new file mode 100644 index 0000000..665b0cd --- /dev/null +++ b/src/mem/io.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include // pid_t + +struct mem_io { + size_t (*read)(const struct mem_io *io, void *ptr, const size_t offset, const size_t size); + size_t (*write)(const struct mem_io *io, const void *ptr, const size_t offset, const size_t size); + void (*cleanup)(struct mem_io *io); + void *backing; + pid_t pid; +}; + +static inline void +mem_io_release(struct mem_io *io) +{ + if (io->cleanup) + io->cleanup(io); + *io = (struct mem_io){0}; +} + +void +mem_io_release(struct mem_io *io); + +bool +mem_io_uio_init(struct mem_io *io, const pid_t pid); + +bool +mem_io_ptrace_init(struct mem_io *io, const pid_t pid); diff --git a/src/ptrace-address-rw.c b/src/ptrace-address-rw.c new file mode 100644 index 0000000..21736ad --- /dev/null +++ b/src/ptrace-address-rw.c @@ -0,0 +1,12 @@ +#include "cli/cli.h" +#include "mem/io.h" + +// This address-rw uses ptrace +// This works with older kernels, but it also ensures non racy read/writes, as it stops the process. +// It's recommended to `setcap cap_sys_ptrace=eip ptrace-region-rw` to run this tool without sudo + +int +main(int argc, const char *argv[]) +{ + return proc_address_rw(argc, argv, mem_io_ptrace_init); +} diff --git a/src/ptrace-region-rw.c b/src/ptrace-region-rw.c index 135c2a5..02d6b0c 100644 --- a/src/ptrace-region-rw.c +++ b/src/ptrace-region-rw.c @@ -1,5 +1,5 @@ -#include "cli/proc-region-rw.h" -#include "io/io.h" +#include "cli/cli.h" +#include "mem/io.h" // This region-rw uses ptrace // This works with older kernels, but it also ensures non racy read/writes, as it stops the process. @@ -8,5 +8,5 @@ int main(int argc, const char *argv[]) { - return proc_region_rw(argc, argv, io_ptrace_init); + return proc_region_rw(argc, argv, mem_io_ptrace_init); } diff --git a/src/uio-address-rw.c b/src/uio-address-rw.c new file mode 100644 index 0000000..1606fa4 --- /dev/null +++ b/src/uio-address-rw.c @@ -0,0 +1,13 @@ +#include "cli/cli.h" +#include "mem/io.h" + +// This address-rw uses uio +// It needs recent kernel, but may be racy as it reads / writes while process is running. +// Ideal for realtime memory tools. +// It's recommended to `setcap cap_sys_ptrace=eip uio-region-rw` to run this tool without sudo + +int +main(int argc, const char *argv[]) +{ + return proc_address_rw(argc, argv, mem_io_uio_init); +} diff --git a/src/uio-region-rw.c b/src/uio-region-rw.c index 96cac49..1daa763 100644 --- a/src/uio-region-rw.c +++ b/src/uio-region-rw.c @@ -1,5 +1,5 @@ -#include "cli/proc-region-rw.h" -#include "io/io.h" +#include "cli/cli.h" +#include "mem/io.h" // This region-rw uses uio // It needs recent kernel, but may be racy as it reads / writes while process is running. @@ -9,5 +9,5 @@ int main(int argc, const char *argv[]) { - return proc_region_rw(argc, argv, io_uio_init); + return proc_region_rw(argc, argv, mem_io_uio_init); } diff --git a/src/util.h b/src/util.h index d62186c..8dc2fb9 100644 --- a/src/util.h +++ b/src/util.h @@ -2,6 +2,18 @@ #include +static inline bool +is_hex(const char *str) +{ + return (strlen(str) > 2 && str[0] == '0' && str[1] == 'x'); +} + +static inline unsigned long long int +hexdecstrtoull(const char *str, char **endptr) +{ + return strtoull(str, endptr, (is_hex(str) ? 16 : 10)); +} + struct region { size_t start, end, offset; }; -- cgit v1.2.3