diff options
author | Stuart Bennett <sb476@cam.ac.uk> | 2007-12-08 00:20:15 +0000 |
---|---|---|
committer | Stuart Bennett <sb476@cam.ac.uk> | 2007-12-08 00:21:08 +0000 |
commit | 234f9eabcf4269774decf2b969d057716fe52981 (patch) | |
tree | ee53525a9a39028d161015969820f21d43df05c3 | |
parent | fb251a452f572b6084e5bd0253804da363f7523b (diff) |
Add deloopify, a trace compactor
Also some makefile fettling
-rw-r--r-- | README | 3 | ||||
-rw-r--r-- | deloopify.c | 181 | ||||
-rw-r--r-- | makefile | 55 | ||||
-rw-r--r-- | vbtracetool.c | 3 |
4 files changed, 198 insertions, 44 deletions
@@ -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; +} @@ -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> |