summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart Bennett <sb476@cam.ac.uk>2007-12-08 00:20:15 +0000
committerStuart Bennett <sb476@cam.ac.uk>2007-12-08 00:21:08 +0000
commit234f9eabcf4269774decf2b969d057716fe52981 (patch)
treeee53525a9a39028d161015969820f21d43df05c3
parentfb251a452f572b6084e5bd0253804da363f7523b (diff)
Add deloopify, a trace compactor
Also some makefile fettling
-rw-r--r--README3
-rw-r--r--deloopify.c181
-rw-r--r--makefile55
-rw-r--r--vbtracetool.c3
4 files changed, 198 insertions, 44 deletions
diff --git a/README b/README
index 4fef5ab..5d84783 100644
--- a/README
+++ b/README
@@ -29,6 +29,9 @@ this shell script will run vbtracetool in such a way to do a POST
try either of these in x and lose.
+Bonus trace processor:
+"./deloopify TRACENAME" will compact loops in your trace
+
Killing:
do not interrupt, once started -- you will likely earn yourself a hung machine
if you really really don't like what's happening, turn the power off
diff --git a/deloopify.c b/deloopify.c
new file mode 100644
index 0000000..c9d8a5f
--- /dev/null
+++ b/deloopify.c
@@ -0,0 +1,181 @@
+/*
+ * deloopify, a loop compactor for vbtracetool generated traces
+ *
+ * Copyright 2007 Stuart Bennett <sb476@cam.ac.uk>
+ *
+ * This program is released under the terms of the GNU General Public License, version 2
+ */
+
+#include <pci/pci.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* length of sliding history of line beginnings */
+#define MAX_LOOP_LEN 2000
+
+bool loop_concluded(FILE *tracef, uint16_t loopendip)
+{
+ /* from the current position in the file (assumed to be a loop
+ * instruction), see if the next ip is 2 bigger (implies we fell out
+ * of the loop)
+ *
+ * if we hit eof, behave as if loop ended, and reset eof, so end of
+ * file gets read and written out by the caller
+ */
+ fpos_t loopendpos;
+ char line[180];
+
+ fgetpos(tracef, &loopendpos);
+ do {
+ if (!fgets(line, 180, tracef))
+ break; // eof
+ } while (line[4] != ':');
+ fsetpos(tracef, &loopendpos);
+ clearerr(tracef);
+
+ if (strtoul(&line[5], NULL, 16) != loopendip + 2) // we looped
+ return false;
+
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *tracef, *outf;
+ long lineno = -1;
+ char sig[MAX_LOOP_LEN][100];
+ char loopsig[] = "Loop";
+
+ char outname[1024];
+ strcpy(outname, argv[1]);
+ strcat(outname, "-deloopd");
+ if (!(tracef = fopen(argv[1], "r"))) {
+ printf("File open failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (!(outf = fopen(outname, "w"))) {
+ printf("File open failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ memset(sig, 0, sizeof(sig));
+ while (!feof(tracef)) {
+ char line[180];
+
+ if (!fgets(line, 180, tracef))
+ break; // eof
+ fwrite(line, strlen(line), 1, outf);
+ lineno += 1;
+ /* we maintain a sliding history of previous line beginnings in sig,
+ * so we can search for the cs:ip of where the loop began
+ */
+ strncpy(sig[lineno % MAX_LOOP_LEN], line, 9);
+ /* this is only necessary if you want intelligible debug printing */
+//sig[lineno % MAX_LOOP_LEN][9] = 0;
+
+ if (strstr(line, "LOOP")) {
+ uint16_t loopendip = strtoul(&line[5], NULL, 16);
+
+ /* if the trace doesn't loop, there's nothing to do */
+ if (loop_concluded(tracef, loopendip))
+ goto next;
+
+//fprintf(outf, "loop\n");
+ /* adapt the loop ip detection for LOOP, LOOPE and LOOPNE opcodes */
+ int jumpipofs = 0;
+ switch (line[34]) {
+ case 'E':
+ jumpipofs += 1;
+ break;
+ case 'N':
+ jumpipofs += 2;
+ break;
+ }
+
+ uint16_t loopcs = strtoul(&line[0], NULL, 16);
+ uint16_t loopstartip;
+ /* for some reason, the loop ip is occasionally 8 bytes */
+ if ((strtoul(&line[35], NULL, 16) & 0xffff0000) == 0xffff0000)
+ loopstartip = strtoul(&line[39 + jumpipofs], NULL, 16);
+ else
+ loopstartip = strtoul(&line[35 + jumpipofs], NULL, 16);
+ /* the 'signature' (cs:ip) of where the loop started */
+ char startsig[10];
+ sprintf(startsig, "%04x:%04x", loopcs, loopstartip);
+
+ int looplen = 1;
+ int bonus = 0;
+ for ( ; looplen < MAX_LOOP_LEN; looplen++) {
+ /* on our way back through the sliding sig list, retrive the
+ * uncontracted length of any previously compacted loops
+ */
+ if (!strncmp(loopsig, sig[(lineno - looplen) % MAX_LOOP_LEN], 4)) {
+ int len, mult;
+ sscanf(sig[(lineno - looplen) % MAX_LOOP_LEN], "Loop of last %d lines repeats a further %d times", &len, &mult);
+ if (mult)
+ bonus += len * mult - 1;
+ }
+ /* when we find the loop start, stop */
+ if (!strncmp(startsig, sig[(lineno - looplen) % MAX_LOOP_LEN], 9))
+ break;
+ }
+
+ if (looplen == MAX_LOOP_LEN) { /* fail */
+ printf("Didn't find start of loop -- try increasing MAX_LOOP_LEN?\n");
+ exit(EXIT_FAILURE);
+ }
+
+//fprintf(outf, "loop sig %s, startsig %s, found %s, looplen %d, bonus %d\n", sig[lineno % MAX_LOOP_LEN], startsig, sig[(lineno - looplen - 4) % MAX_LOOP_LEN], looplen, bonus);
+ /* Assume loop instr adds 4 lines */
+ looplen += 4;
+
+ fpos_t loopendpos;
+ int loopcount = 0;
+ /* slurp until the loop terminates */
+ while (!loop_concluded(tracef, loopendip)) {
+ fgetpos(tracef, &loopendpos);
+ /* we know the loop length from finding the signature, so move
+ * forward the same length plus the length of any previous
+ * contractions (as stuff further into the file will not be
+ * contracted) and see if we're at another loop instruction
+ */
+ for (int i = 0; i < looplen + bonus; i++)
+ if (!fgets(line, 180, tracef)) { // eof
+ clearerr(tracef);
+ goto dissimilar;
+ }
+ /* if we are, treat this loop as identical, and carry on */
+ if (!strncmp(line, sig[lineno % MAX_LOOP_LEN], 9)) {
+ loopcount++;
+ continue;
+ }
+dissimilar:
+ /* if we're not, this loop is not identical, and cannot be compacted */
+ fsetpos(tracef, &loopendpos);
+//fprintf(outf, "loop changed size -- looking for %s, got %s\n", sig[lineno % MAX_LOOP_LEN], line);
+ break;
+ }
+ /* if we found one or more identical length loops, replace them in the
+ * output with a contraction message. Also add this message to the
+ * sliding signature log, so that it can be counted in, if this loop
+ * is inside another loop
+ */
+ if (loopcount) {
+ char loopstr[100];
+ snprintf(loopstr, 100, "Loop of last %d lines repeats a further %d times", looplen, loopcount);
+ fprintf(outf, "\n%s\n\n\n", loopstr);
+ lineno += 1;
+ strncpy(sig[lineno % MAX_LOOP_LEN], loopstr, 100);
+ }
+next:
+ continue;
+ }
+ }
+
+ return 0;
+}
diff --git a/makefile b/makefile
index 5019daf..ddf3f71 100644
--- a/makefile
+++ b/makefile
@@ -1,40 +1,8 @@
-#############################################################################
-#
-# Realmode X86 Emulator Library
-#
-# Copyright (C) 1996-1999 SciTech Software, Inc.
-#
-# ========================================================================
-#
-# Permission to use, copy, modify, distribute, and sell this software and
-# its documentation for any purpose is hereby granted without fee,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of the authors not be used
-# in advertising or publicity pertaining to distribution of the software
-# without specific, written prior permission. The authors makes no
-# representations about the suitability of this software for any purpose.
-# It is provided "as is" without express or implied warranty.
-#
-# THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-# EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
-# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-# PERFORMANCE OF THIS SOFTWARE.
-#
-# ========================================================================
-#
-# Descripton: Linux specific makefile for the x86emu library.
-#
-#############################################################################
+LIBX86EMU = libx86emu.a
+VBTT=vbtracetool
+DL=deloopify
-TARGETLIB = libx86emu.a
-
-PROG=vbtracetool
-
-OBJS=\
+LIBX86EMUOBJS=\
debug.o \
decode.o \
fpu.o \
@@ -50,13 +18,16 @@ vbtracetool.o \
thunk.o \
x86-common.o
-all: $(PROG)
+all: $(VBTT) $(DL)
+
+$(LIBX86EMU): $(LIBX86EMUOBJS)
+ ar r $(LIBX86EMU) $(LIBX86EMUOBJS)
-$(PROG): $(TARGETLIB) $(VBTTOBJS)
- gcc $(VBTTOBJS) $(TARGETLIB) -lpci -lz -s -o $(PROG)
+$(VBTT): $(LIBX86EMU) $(VBTTOBJS)
+ gcc $(VBTTOBJS) $(LIBX86EMU) -lpci -lz -s -o $(VBTT)
-$(TARGETLIB): $(OBJS)
- ar r $(TARGETLIB) $(OBJS)
+$(DL):
+ gcc $(CFLAGS) -std=gnu99 $(shell getconf LFS_CFLAGS) $(DL).c -o $(DL)
INCS = -I. -Ix86emu
CFLAGS = -DDEBUG -Wall -O3
@@ -67,6 +38,6 @@ CFLAGS = -DDEBUG -Wall -O3
distclean: clean
clean:
- rm -f *.a *.o *~ $(PROG)
+ rm -f *.a *.o *~ $(VBTT) $(DL)
install:
diff --git a/vbtracetool.c b/vbtracetool.c
index 2b6472a..84ddf80 100644
--- a/vbtracetool.c
+++ b/vbtracetool.c
@@ -5,8 +5,7 @@
*
* Based on vbetool.c, Copyright Matthew Garrett <mjg59@srcf.ucam.org>
*
- * This program is released under the terms of the GNU General Public License,
- * version 2
+ * This program is released under the terms of the GNU General Public License, version 2
*/
#include <pci/pci.h>