# HG changeset patch # User Michael Spacefalcon # Date 1404463592 0 # Node ID 10c0cdc18208a521e44d317968c81b0d71b71338 # Parent 77cd647375e5e31918b15bf96f6c6ed3cb69ad77 objgrep-fe written, compiles diff -r 77cd647375e5 -r 10c0cdc18208 .hgignore --- a/.hgignore Fri Jul 04 06:34:33 2014 +0000 +++ b/.hgignore Fri Jul 04 08:46:32 2014 +0000 @@ -37,6 +37,7 @@ ^mysteryffs/scan1$ ^objgrep/objgrep$ +^objgrep/objgrep-fe$ ^pirollback/analyze$ ^pirollback/catino$ diff -r 77cd647375e5 -r 10c0cdc18208 objgrep/Makefile --- a/objgrep/Makefile Fri Jul 04 06:34:33 2014 +0000 +++ b/objgrep/Makefile Fri Jul 04 08:46:32 2014 +0000 @@ -1,18 +1,21 @@ CC= gcc CFLAGS= -O2 -PROG= objgrep +PROGS= objgrep objgrep-fe OBJS= dumpmatch.o globals.o grep.o lowlevel.o main.o mkpattern.o tables.o HDRS= coffconst.h filestruct.h globals.h intstruct.h -all: ${PROG} +all: ${PROGS} -${PROG}: ${OBJS} +objgrep: ${OBJS} ${CC} -o $@ ${OBJS} ${OBJS}: ${HDRS} +objgrep-fe: frontend.c + ${CC} ${CFLAGS} -o $@ frontend.c + install: - install -c -o bin -g bin -m 755 ${PROG} /usr/local/bin + install -c -o bin -g bin -m 755 ${PROGS} /usr/local/bin clean: - rm -f *.o ${PROG} *errs + rm -f *.o ${PROGS} *errs diff -r 77cd647375e5 -r 10c0cdc18208 objgrep/frontend.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/objgrep/frontend.c Fri Jul 04 08:46:32 2014 +0000 @@ -0,0 +1,292 @@ +/* + * This program is a front-end to objgrep. It takes an ASCII text file as + * input that lists the modules and sections to be grepped for, and it + * invokes objgrep via popen() for each listed section, all on the same + * unknown binary. We collect the symbol addresses printed by objgrep + * via our pipe, and then we sort them to produce the final report. + */ + +#include +#include +#include +#include +#include +#include + +#define RAM_BOUNDARY 0x800000 + +#define SYMFLAG_AMBIG 8 +#define SYMSRC_TEXTMATCH 4 +#define SYMSRC_EXTRELOC 2 +#define SYMSRC_INTRELOC 1 + +struct symbol { + char *name; + unsigned value; + int flags; + struct symbol *next; +}; + +struct symbol *flash_symbols, *ram_symbols; +unsigned num_flash_symbols, num_ram_symbols; +char *binfilename; + +enter_symbol(name, valstr, symsrc) + char *name, *valstr; +{ + struct symbol *newsym; + + newsym = malloc(sizeof(struct symbol) + strlen(name) + 1); + if (!newsym) { + perror("malloc"); + exit(1); + } + newsym->name = (char *)(newsym + 1); + strcpy(newsym->name, name); + newsym->value = strtoul(valstr, 0, 16); + newsym->flags = symsrc; + if (newsym->value < RAM_BOUNDARY) { + newsym->next = flash_symbols; + flash_symbols = newsym; + num_flash_symbols++; + } else { + newsym->next = ram_symbols; + ram_symbols = newsym; + num_ram_symbols++; + } +} + +process_section(objfile, secname) + char *objfile, *secname; +{ + char cmdline[1024], linebuf[512], *cp, *fields[3]; + FILE *f; + int symsrc, i; + static char headline_textmatch[] = "This source section's symbols:"; + static char headline_extreloc[] = "Externals deduced from relocs:"; + static char headline_intreloc[] = + "This module's symbols deduced from section relocs:"; + + sprintf(cmdline, "objgrep -rs %s %s %s", objfile, secname, binfilename); + f = popen(cmdline, "r"); + if (!f) { + perror("popen"); + exit(1); + } + symsrc = 0; + while (fgets(linebuf, sizeof linebuf, f)) { + cp = index(linebuf, '\n'); + if (!cp) { + fprintf(stderr, + "error: objgrep output line has no terminating newline\n"); + exit(1); + } + *cp = '\0'; + if (!strcmp(linebuf, headline_textmatch)) { + symsrc = SYMSRC_TEXTMATCH; + continue; + } + if (!strcmp(linebuf, headline_extreloc)) { + symsrc = SYMSRC_EXTRELOC; + continue; + } + if (!strcmp(linebuf, headline_intreloc)) { + symsrc = SYMSRC_INTRELOC; + continue; + } + cp = linebuf; + for (i = 0; ; i++) { + while (isspace(*cp)) + cp++; + if (!*cp) + break; + if (i == 3) { + i++; + break; + } + for (fields[i] = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + } + if (i != 3) + continue; + if (fields[1][0] != '=' || fields[1][1]) + continue; + if (!symsrc) { + fprintf(stderr, + "error: symbol output from objgrep w/o source indication\n"); + exit(1); + } + enter_symbol(fields[0], fields[2], symsrc); + } + pclose(f); +} + +process_list_file(listfilename) + char *listfilename; +{ + FILE *f; + char linebuf[512], *objname, *cp, *np; + int lineno; + + f = fopen(listfilename, "r"); + if (!f) { + perror(listfilename); + exit(1); + } + for (lineno = 1; fgets(linebuf, sizeof linebuf, f); lineno++) { + for (cp = linebuf; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') + continue; + for (objname = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { + process_section(objname, ".text"); + continue; + } + while (*cp && *cp != '#') { + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + process_section(objname, np); + while (isspace(*cp)) + cp++; + } + } + fclose(f); +} + +sort_by_value(sym1, sym2) + struct symbol **sym1, **sym2; +{ + if ((*sym1)->value < (*sym2)->value) + return(-1); + if ((*sym1)->value > (*sym2)->value) + return(1); + return(0); +} + +sort_by_name(sym1, sym2) + struct symbol **sym1, **sym2; +{ + int i; + + i = strcmp((*sym1)->name, (*sym2)->name); + if (i) + return i; + else + return sort_by_value(sym1, sym2); +} + +fill_input_array(head, buf) + struct symbol *head, **buf; +{ + struct symbol *sym, **p; + + p = buf; + for (sym = head; sym; sym = sym->next) + *p = sym; +} + +unsigned +dedup_symbols(inbuf, outbuf, total) + struct symbol **inbuf, **outbuf; + unsigned total; +{ + struct symbol **ip, **op, **input_end, *nsym; + + op = outbuf; + input_end = inbuf + total; + for (ip = inbuf; ip < input_end; ip++) { + nsym = *ip; + if (op == outbuf || strcmp(nsym->name, op[-1]->name)) { + *op++ = nsym; + continue; + } + if (nsym->value == op[-1]->value) { + op[-1]->flags |= nsym->flags; + continue; + } + op[-1]->flags |= SYMFLAG_AMBIG; + nsym->flags |= SYMFLAG_AMBIG; + *op++ = nsym; + } + return(op - outbuf); +} + +emit_final_symbols(buf, total) + struct symbol **buf; + unsigned total; +{ + struct symbol **p, **endbuf, *sym; + + endbuf = buf + total; + for (p = buf; p < endbuf; p++) { + sym = *p; + printf("%08X %s (", sym->value, sym->name); + if (sym->flags & SYMSRC_TEXTMATCH) + putchar('S'); + if (sym->flags & SYMSRC_EXTRELOC) + putchar('R'); + if (sym->flags & SYMSRC_INTRELOC) + putchar('r'); + if (sym->flags & SYMFLAG_AMBIG) + fputs(", ambiguous", stdout); + putchar(')'); + putchar('\n'); + } +} + +sort_and_emit_symbols(head, total) + struct symbol *head; + unsigned total; +{ + struct symbol **input, **output; + unsigned final_count; + + input = malloc(sizeof(void *) * total); + if (!input) { + perror("malloc"); + exit(1); + } + fill_input_array(head, input); + qsort(input, total, sizeof(void *), sort_by_name); + output = malloc(sizeof(void *) * total); + if (!output) { + perror("malloc"); + exit(1); + } + final_count = dedup_symbols(input, output, total); + free(input); + qsort(output, final_count, sizeof(void *), sort_by_value); + emit_final_symbols(output, final_count); + free(output); + putchar('\n'); +} + +main(argc, argv) + char **argv; +{ + if (argc != 3) { + fprintf(stderr, "usage: %s listfile binfile\n", argv[0]); + exit(1); + } + binfilename = argv[2]; + process_list_file(argv[1]); + if (flash_symbols) { + printf("Flash symbols:\n\n"); + sort_and_emit_symbols(flash_symbols, num_flash_symbols); + } + if (ram_symbols) { + printf("RAM symbols:\n\n"); + sort_and_emit_symbols(ram_symbols, num_ram_symbols); + } + exit(0); +}