From 9f8de76123bb91967006b60fae7ed511d57ce9c6 Mon Sep 17 00:00:00 2001 From: Colin Patrick McCabe Date: Sun, 21 Aug 2011 21:22:06 -0400 Subject: [PATCH] Initial commit Signed-off-by: Colin McCabe --- Makefile | 21 +++ good.c | 12 ++ grindhouse.go | 30 ++++ grindhouse_test.go | 371 ++++++++++++++++++++++++++++++++++++++++++++++++++++ leaky.c | 11 ++ main.go | 71 ++++++++++ 6 files changed, 516 insertions(+), 0 deletions(-) create mode 100644 Makefile create mode 100644 good.c create mode 100644 grindhouse.go create mode 100644 grindhouse_test.go create mode 100644 leaky.c create mode 100644 main.go diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..31d1a54 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +include $(GOROOT)/src/Make.inc + +package: grindhouse leaky good + +test-clean: clean + rm -f leaky good + +TARG=grindhouse +GOFILES=grindhouse.go \ + main.go +grindhouse: _obj/$(TARG).a $(GOFILES) + $(GC) -I_obj $(GOFILES) + $(LD) -L_obj -o $@ grindhouse.$O + +leaky: leaky.c + $(HOST_CC) -o $@ $< $(CFLAGS) + +good: good.c + $(HOST_CC) -o $@ $< $(CFLAGS) + +include $(GOROOT)/src/Make.pkg diff --git a/good.c b/good.c new file mode 100644 index 0000000..ce661f5 --- /dev/null +++ b/good.c @@ -0,0 +1,12 @@ +#include +#include + +int main(void) +{ + int i = 123; + char outs[128]; + char *c = malloc(100); + snprintf(outs, sizeof(outs), "Guess what is in i! It's %d\n", i); + free(c); + return 0; +} diff --git a/grindhouse.go b/grindhouse.go new file mode 100644 index 0000000..39cc54a --- /dev/null +++ b/grindhouse.go @@ -0,0 +1,30 @@ +package grindhouse + +import "bytes" +import "fmt" +import "io" +import "os" +import "xml" + +type ValgrindInfo struct { + Clean bool +} + +type ValgrindOutput struct { + XMLName xml.Name `xml:"valgrindoutput"` + Protocolversion int `xml:"Protocolversion"` +} + +func ParseValgrindXml(rio io.Reader) (*ValgrindInfo, os.Error) { + var valout ValgrindOutput + xml.Unmarshal(rio, &valout) + fmt.Printf("valout.Protocolversion = %d\n", valout.Protocolversion) + + buffer := bytes.NewBufferString("") + xml.Marshal(buffer, valout) + fmt.Printf("outstring = %s\n", string(buffer.Bytes())) + + vinfo := new(ValgrindInfo) + vinfo.Clean = true + return vinfo, nil +} diff --git a/grindhouse_test.go b/grindhouse_test.go new file mode 100644 index 0000000..2db7923 --- /dev/null +++ b/grindhouse_test.go @@ -0,0 +1,371 @@ +package grindhouse + +import "strings" +import "testing" + +const CLEANXML1 = ` + + + + +4 +memcheck + + + Memcheck, a memory error detector + Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. + Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info + Command: ./good + + +13206 +32361 +memcheck + + + + /usr/bin/valgrind.bin + --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp + --xml-file=/tmp/t + --xml=yes + + + ./good + + + + + RUNNING + + + + + + FINISHED + + + + + + + + + 2 + dl-hack3-cond-1 + + + 2 + glibc-2.5.x-on-SUSE-10.2-(PPC)-2a + + + + +` + +const ERRORXML1 = ` + + + + +4 +memcheck + + + Memcheck, a memory error detector + Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. + Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info + Command: ./leaky + + +7673 +32361 +memcheck + + + + /usr/bin/valgrind.bin + --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp + --xml-file=/tmp/t + --xml=yes + + + ./leaky + + + + + RUNNING + + + + + 0x4 + 1 + UninitValue + Use of uninitialised value of size 8 + + + 0x4E6A76B + /lib/libc-2.11.2.so + _itoa_word + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + _itoa.c + 195 + + + 0x4E6B9B8 + /lib/libc-2.11.2.so + vfprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + vfprintf.c + 1613 + + + 0x4E903F1 + /lib/libc-2.11.2.so + vsnprintf + /home/aurel32/eglibc/eglibc-2.11.2/libio + vsnprintf.c + 120 + + + 0x4E75902 + /lib/libc-2.11.2.so + snprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + snprintf.c + 35 + + + 0x40056D + /mnt/e4test/src/grindhouse/leaky + main + + + + + + 0x5 + 1 + UninitCondition + Conditional jump or move depends on uninitialised value(s) + + + 0x4E6A775 + /lib/libc-2.11.2.so + _itoa_word + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + _itoa.c + 195 + + + 0x4E6B9B8 + /lib/libc-2.11.2.so + vfprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + vfprintf.c + 1613 + + + 0x4E903F1 + /lib/libc-2.11.2.so + vsnprintf + /home/aurel32/eglibc/eglibc-2.11.2/libio + vsnprintf.c + 120 + + + 0x4E75902 + /lib/libc-2.11.2.so + snprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + snprintf.c + 35 + + + 0x40056D + /mnt/e4test/src/grindhouse/leaky + main + + + + + + 0x6 + 1 + UninitCondition + Conditional jump or move depends on uninitialised value(s) + + + 0x4E6D928 + /lib/libc-2.11.2.so + vfprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + vfprintf.c + 1613 + + + 0x4E903F1 + /lib/libc-2.11.2.so + vsnprintf + /home/aurel32/eglibc/eglibc-2.11.2/libio + vsnprintf.c + 120 + + + 0x4E75902 + /lib/libc-2.11.2.so + snprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + snprintf.c + 35 + + + 0x40056D + /mnt/e4test/src/grindhouse/leaky + main + /lib/libc-2.11.2.so + snprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + snprintf.c + 35 + + + 0x40056D + /mnt/e4test/src/grindhouse/leaky + main + 1 + UninitCondition + Conditional jump or move depends on uninitialised value(s) + + + 0x4E6D928 + /lib/libc-2.11.2.so + vfprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + vfprintf.c + 1613 + + + 0x4E903F1 + /lib/libc-2.11.2.so + vsnprintf + /home/aurel32/eglibc/eglibc-2.11.2/libio + vsnprintf.c + 120 + + + 0x4E75902 + /lib/libc-2.11.2.so + snprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + snprintf.c + 35 + + + 0x40056D + /mnt/e4test/src/grindhouse/leaky + main + + + + + + 0x7 + 1 + UninitCondition + Conditional jump or move depends on uninitialised value(s) + + + 0x4E6BAA6 + /lib/libc-2.11.2.so + vfprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + vfprintf.c + 1613 + + + 0x4E903F1 + /lib/libc-2.11.2.so + vsnprintf + /home/aurel32/eglibc/eglibc-2.11.2/libio + vsnprintf.c + 120 + + + 0x4E75902 + /lib/libc-2.11.2.so + snprintf + /home/aurel32/eglibc/eglibc-2.11.2/stdio-common + snprintf.c + 35 + + + 0x40056D + /mnt/e4test/src/grindhouse/leaky + main + + + + + + + FINISHED + + + + + 0x8 + 1 + Leak_DefinitelyLost + + 100 bytes in 1 blocks are definitely lost in loss record 1 of 1 + 100 + 1 + + + + 0x4C244E8 + /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so + malloc + /build/buildd-valgrind_3.6.0~svn11254+nmu1-amd64-08RYEm/valgrind-3.6.0~svn11254+nmu1/coregrind/m_replacemalloc + vg_replace_malloc.c + 236 + + + 0x400548 + /mnt/e4test/src/grindhouse/leaky + main + + + +` + +func expectCleanToStr(e bool) string { + if (e) { + return "clean"; + } + return "dirty"; +} + +func doParseValgrindXml(desc string, xml string, + t *testing.T, expectClean bool) { + vinfo, err := ParseValgrindXml(strings.NewReader(xml)) + if (err != nil) { + t.Errorf("got parse error!") + return + } + if (vinfo.Clean != expectClean) { + t.Errorf("expected %s to be %s, but it was %s!", + desc, expectCleanToStr(expectClean), expectCleanToStr(vinfo.Clean)) + return + } +} + +func TestCleanXml1(t *testing.T) { + doParseValgrindXml("cleanXml1", CLEANXML1, t, true) +} + +func TestErrorXml1(t *testing.T) { + doParseValgrindXml("errorXml1", ERRORXML1, t, false) +} diff --git a/leaky.c b/leaky.c new file mode 100644 index 0000000..5fefa0c --- /dev/null +++ b/leaky.c @@ -0,0 +1,11 @@ +#include +#include + +int main(void) +{ + int i; + char outs[128]; + char *c = malloc(100); + snprintf(outs, sizeof(outs), "Guess what is in i! It's %d\n", i); + return 0; +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..c3673b1 --- /dev/null +++ b/main.go @@ -0,0 +1,71 @@ +package grindhouse + +import "flag" +import "fmt" +import "os" + +/* + * Grindhouse + * + * Recommended valgrind options: + * valgrind --xml=yes --xml-file= + */ + +func usage() { + fmt.Fprintf(os.Stderr, +`%s: a valgrind XML file analyzer. +This program analyzes valgrind XML output files and summarizes them. + +Usage: %s [opts] [files] +Options: +-h: this help message +`, os.Args[0], os.Args[0]) +} + +var getHelp = flag.Bool("h", false, "See usage") + +func handleFile(filename string) os.Error { + file, err := os.Open(filename) + if (err != nil) { + fmt.Fprintf(os.Stderr, "Failed to open file %s\n", filename) + return err + } + defer file.Close() + vinfo, err := ParseValgrindXml(file) + if (err != nil) { + fmt.Fprintf(os.Stderr, "Failed to parse file %s\n", filename) + return err + } + if !vinfo.Clean { + return os.EAFNOSUPPORT + } + return nil +} + +func main() { + ret := 0 + flag.Usage = usage + flag.Parse() + if (*getHelp) { + usage() + os.Exit(0) + } + filenames := make([]string, flag.NArg()) + for i := 0; i < flag.NArg(); i++ { + filenames[i] = flag.Arg(i) + } + if (flag.NArg() == 0) { + fmt.Fprintf(os.Stderr, "You must give at least one file to open as an argument.") + usage() + os.Exit(1) + } + for i := 0; i < len(filenames); i++ { + if handleFile(filenames[i]) != nil { + ret = 1 + } + } + if (ret != 0) { + fmt.Fprintf(os.Stderr, "Errors were encountered.") + } + os.Exit(ret) +} -- 1.6.6.rc1.39.g9a42