changeset 174:10c0cdc18208

objgrep-fe written, compiles
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Fri, 04 Jul 2014 08:46:32 +0000
parents 77cd647375e5
children 928ed52930aa
files .hgignore objgrep/Makefile objgrep/frontend.c
diffstat 3 files changed, 301 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- 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$
--- 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
--- /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 <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#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);
+}