summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/brute-map.bash4
-rw-r--r--src/binsearch.c51
2 files changed, 40 insertions, 15 deletions
diff --git a/contrib/brute-map.bash b/contrib/brute-map.bash
index 4a5a811..a05e915 100755
--- a/contrib/brute-map.bash
+++ b/contrib/brute-map.bash
@@ -1,11 +1,11 @@
#!/bin/bash
-# usage: ./brute-map.bash pid file [window-size]
+# usage: ./brute-map.bash pid file [window-size] < regions
# Sometimes region offsets aren't available, but we know that some regions map a file
# Fix the region offsets by bruteforcing the offsets from a known file
while read -r region; do
offset=$(printf '%d' "0x$(awk '{print $3}' <<<"$region")")
if ((offset == 0)); then
- offset=$(binsearch <(ptrace-region-rw "$1" read <<<"$region" 2>/dev/null | bintrim) $3 < "$2")
+ offset=$(binsearch <(ptrace-region-rw "$1" read <(printf '%s\n' "$region") | bintrim) first $3 < "$2" 2>/dev/null)
if [[ -n "$offset" ]]; then
hex=$(printf '%.8x' "$offset")
awk '{printf "%s %s %s %s %s %s\n", $1, $2, "'"$hex"'", $4, $5, $6, $7}' <<<"$region"
diff --git a/src/binsearch.c b/src/binsearch.c
index a4195ba..d382c5a 100644
--- a/src/binsearch.c
+++ b/src/binsearch.c
@@ -2,12 +2,16 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
+#include <util.h>
#include <err.h>
+static bool FOUND = false;
+
static void
usage(const char *argv0)
{
- fprintf(stderr, "usage: %s needle [window-size] < haystack\n", argv0);
+ fprintf(stderr, "usage: %s needle first [window-size] < haystack\n"
+ " %s needle all [window-size] < haystack\n", argv0, argv0);
exit(EXIT_FAILURE);
}
@@ -23,14 +27,17 @@ search(const char *haystack, const char *needle, const size_t window_size)
}
static void
-search_and_exit_if_match(const char *haystack, const char *needle, const size_t window_size, const size_t offset)
+search_and_print_if_match(const char *haystack, const char *needle, const size_t window_size, const size_t offset, const bool exit_on_match)
{
const char *match;
if ((match = search(haystack, needle, window_size))) {
+ FOUND = true;
printf("%zu\n", offset + match - haystack);
- free((void*)needle);
- free((void*)haystack);
- exit(EXIT_SUCCESS);
+ if (exit_on_match) {
+ free((void*)needle);
+ free((void*)haystack);
+ exit(EXIT_SUCCESS);
+ }
}
}
@@ -41,10 +48,23 @@ main(int argc, const char *argv[])
size_t window_size = 4096 * 1024;
bool has_window_size = false;
- if (argc < 2)
+ if (argc < 3)
usage(argv[0]);
- else if (argc > 2) {
- window_size = strtoull(argv[2], NULL, 10);
+
+ enum {
+ FIRST,
+ ALL
+ } mode;
+
+ if (!strcmp(argv[2], "first"))
+ mode = FIRST;
+ else if (!strcmp(argv[2], "all"))
+ mode = ALL;
+ else
+ errx(EXIT_FAILURE, "mode must be first or all");
+
+ if (argc > 3) {
+ window_size = hexdecstrtoull(argv[3], NULL);
has_window_size = true;
}
@@ -55,7 +75,12 @@ main(int argc, const char *argv[])
if (!has_window_size) {
fseek(f, 0, SEEK_END);
const long tell = ftell(f);
- window_size = (tell > 0 ? (size_t)tell : window_size);
+
+ if (tell < 0)
+ warnx("can't figure out the size of a needle, not a normal file? fallbacking to a window size of %zu bytes", window_size);
+ else
+ window_size = tell;
+
fseek(f, 0, SEEK_SET);
}
@@ -71,14 +96,14 @@ main(int argc, const char *argv[])
err(EXIT_FAILURE, "calloc");
size_t rd = 0, offset = 0;
- while ((rd = fread(haystack + window_size * !!offset, 1 + !offset, window_size, stdin))) {
- search_and_exit_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset);
+ while ((rd = fread(haystack + window_size * !!offset, 1, window_size * (1 + !offset), stdin))) {
+ search_and_print_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset, (mode == FIRST));
offset += window_size;
memmove(haystack, haystack + window_size, window_size);
}
- search_and_exit_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset);
+ search_and_print_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset, (mode == FIRST));
free(needle);
free(haystack);
- return EXIT_FAILURE;
+ return (FOUND ? EXIT_SUCCESS : EXIT_FAILURE);
}