/* * Search through TRC_MEM output for references to a certain areas of * memory. * * Usage: $0 [flags] spec [spec ...] * * Each spec can be begin-end or begin+size, where all numbers are in * hex. The lines being searched are taken from stdin; matching lines * are printed to stdout (by default; see the flags, below). Specs * always include the base but not the end; to put it another way, the * ranges are [base,end). (The form with begin and size is equivalent * to the begin-and-end form where end equals begin+size.) * * flags can be: * * -all * Print even non-matching lines. (Without at least one * of the other flags, this causes this program to * degenerate to a crippled variant of cat(1).) * * -hl * Highlight matching lines with backspace-underscore * sequences. * * -prefix STR * Prefix STR to matching lines. * * -nprefix STR * Prefix STR to non-matching lines. * * -suffix STR * Suffix STR to matching lines. * * -nsuffix STR * Suffix STR to non-matching lines. * * If -hl is combined with -prefix and/or -suffix, the highlighting * happens before the prefixing/suffixing - that is, the prefix/suffix * does not get highlighting. Also, of the data, only the bytes * overlapping at least one spec are highlighted. * * If -prefix is given more than once, the last-specified value is the * one that's used. Similar remarks apply to -suffix, -nprefix, and * -nsuffix. */ #include #include #include #include #include extern const char *__progname; typedef struct spec SPEC; struct spec { uint32_t base; uint32_t end; } ; static int print_all = 0; static int highlight = 0; static const char *prefix = 0; static const char *nprefix = 0; static const char *suffix = 0; static const char *nsuffix = 0; static int nspecs; static SPEC *specs; #define Cisdigit(x) isdigit((unsigned char)(x)) #define Cisxdigit(x) isxdigit((unsigned char)(x)) static void parse_spec(const char *str, SPEC *spec) { unsigned long int v; uint32_t v32; char *ep; char sep; const char *n2str; v = strtoul(str,&ep,16); if (ep == str) { fprintf(stderr,"%s: bad spec `%s' (no base address)\n",__progname,str); exit(1); } v32 = v; if (v32 != v) { fprintf(stderr,"%s: bad spec `%s' (out-of-range base address)\n",__progname,str); exit(1); } spec->base = v32; str = ep; sep = *str++; switch (sep) { case '-': n2str = "end address"; break; case '+': n2str = "size"; break; default: fprintf(stderr,"%s: bad spec `%s' (invalid separator)\n",__progname,str); exit(1); break; } v = strtoul(str,&ep,16); if (ep == str) { fprintf(stderr,"%s: bad spec `%s' (no %s)\n",__progname,str,n2str); exit(1); } if (*ep) { fprintf(stderr,"%s: bad spec `%s' (junk after %s)\n",__progname,str,n2str); exit(1); } v32 = v; if (v32 != v) { fprintf(stderr,"%s: bad spec `%s' (out-of-range %s)\n",__progname,str,n2str); exit(1); } switch (sep) { case '-': spec->end = v32; break; case '+': spec->end = spec->base + v32; break; default: abort(); break; } } static void setup(int ac, char **av) { int i; int errs; errs = 0; while ((ac >= 2) && (av[1][0] == '-')) { i = 1; if (! strcmp(av[1],"-all")) { print_all = 1; } else if (! strcmp(av[1],"-hl")) { highlight = 1; } else if (! strcmp(av[1],"-prefix")) { if (ac >= 3) { prefix = av[2]; i = 2; } else { fprintf(stderr,"%s: %s requires a following argument\n",__progname,av[1]); errs = 1; } } else if (! strcmp(av[1],"-nprefix")) { if (ac >= 3) { nprefix = av[2]; i = 2; } else { fprintf(stderr,"%s: %s requires a following argument\n",__progname,av[1]); errs = 1; } } else if (! strcmp(av[1],"-suffix")) { if (ac >= 3) { suffix = av[2]; i = 2; } else { fprintf(stderr,"%s: %s requires a following argument\n",__progname,av[1]); errs = 1; } } else if (! strcmp(av[1],"-nsuffix")) { if (ac >= 3) { nsuffix = av[2]; i = 2; } else { fprintf(stderr,"%s: %s requires a following argument\n",__progname,av[1]); errs = 1; } } else { fprintf(stderr,"%s: unrecognized flag `%s'\n",__progname,av[1]); errs = 1; } ac -= i; av += i; } if (ac < 2) { fprintf(stderr,"Usage: %s [flags] spec [spec ...]\n",__progname); exit(1); } nspecs = ac - 1; specs = malloc(nspecs*sizeof(SPEC)); for (i=nspecs-1;i>=0;i--) { parse_spec(av[i+1],&specs[i]); } } static int want(const char *s0, int *xep, int *xbp, uint32_t *abp) { const char *s; unsigned long int uli; uint32_t v32; char *ep; int n; int sx; SPEC *spec; s = s0; while (*s && Cisdigit(*s)) s ++; if (*s++ != ':') return(0); if (*s++ != ' ') return(0); while (*s && Cisdigit(*s)) s ++; if (*s++ != ':') return(0); if (*s++ != ' ') return(0); switch (*s++) { case 'r': case 'w': case 'x': break; default: return(0); } if (*s++ != ':') return(0); *xep = s - s0; if (*s++ != ' ') return(0); uli = strtoul(s,&ep,16); if (ep == s) return(0); if (*ep != ':') return(0); v32 = uli; if (v32 != uli) return(0); *abp = v32; s = ep + 1; n = 0; *xbp = s - s0; while ((s[0] == ' ') && Cisxdigit(s[1]) && Cisxdigit(s[2])) { n ++; s += 3; } if (s[0]) return(0); if (n < 1) return(0); for (sx=nspecs-1;sx>=0;sx--) { spec = &specs[sx]; if ((spec->end <= v32) || (v32+n <= spec->base)) continue; return(1); } return(0); } static int covered_address(uint32_t a) { int sx; SPEC *s; for (sx=nspecs-1;sx>=0;sx--) { s = &specs[sx]; if ((a >= s->base) && (a < s->end)) return(1); } return(0); } static void process(void) { char *b; int l; int a; int c; int i; int pw; int bx; uint32_t ab; uint32_t ba; int pac; int ac; b = 0; a = 0; l = 0; while (1) { c = getchar(); if (c == EOF) { if (l > 0) fprintf(stderr,"%s: partial line ignored at end of input\n",__progname); break; } if (l >= a) b = realloc(b,a=l+8); b[l++] = c; if (c == '\n') { b[--l] = '\0'; if (want(b,&pw,&bx,&ab)) { if (prefix) printf("%s",prefix); if (highlight) { for (i=0;i