Initial commit master
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Mon, 22 Aug 2011 01:22:06 +0000 (21:22 -0400)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Mon, 22 Aug 2011 01:22:06 +0000 (21:22 -0400)
Signed-off-by: Colin McCabe <cmccabe@alumni.cmu.edu>

Makefile [new file with mode: 0644]
good.c [new file with mode: 0644]
grindhouse.go [new file with mode: 0644]
grindhouse_test.go [new file with mode: 0644]
leaky.c [new file with mode: 0644]
main.go [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..ce661f5
--- /dev/null
+++ b/good.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+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 (file)
index 0000000..39cc54a
--- /dev/null
@@ -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 (file)
index 0000000..2db7923
--- /dev/null
@@ -0,0 +1,371 @@
+package grindhouse
+
+import "strings"
+import "testing"
+
+const CLEANXML1 = `
+<?xml version="1.0"?>
+
+<valgrindoutput>
+
+<protocolversion>4</protocolversion>
+<protocoltool>memcheck</protocoltool>
+
+<preamble>
+  <line>Memcheck, a memory error detector</line>
+  <line>Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.</line>
+  <line>Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info</line>
+  <line>Command: ./good</line>
+</preamble>
+
+<pid>13206</pid>
+<ppid>32361</ppid>
+<tool>memcheck</tool>
+
+<args>
+  <vargv>
+    <exe>/usr/bin/valgrind.bin</exe>
+    <arg>--suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp</arg>
+    <arg>--xml-file=/tmp/t</arg>
+    <arg>--xml=yes</arg>
+  </vargv>
+  <argv>
+    <exe>./good</exe>
+  </argv>
+</args>
+
+<status>
+  <state>RUNNING</state>
+  <time>00:00:00:00.038 </time>
+</status>
+
+
+<status>
+  <state>FINISHED</state>
+  <time>00:00:00:00.363 </time>
+</status>
+
+<errorcounts>
+</errorcounts>
+
+<suppcounts>
+  <pair>
+    <count>2</count>
+    <name>dl-hack3-cond-1</name>
+  </pair>
+  <pair>
+    <count>2</count>
+    <name>glibc-2.5.x-on-SUSE-10.2-(PPC)-2a</name>
+  </pair>
+</suppcounts>
+
+</valgrindoutput>
+`
+
+const ERRORXML1 = `
+<?xml version="1.0"?>
+
+<valgrindoutput>
+
+<protocolversion>4</protocolversion>
+<protocoltool>memcheck</protocoltool>
+
+<preamble>
+  <line>Memcheck, a memory error detector</line>
+  <line>Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.</line>
+  <line>Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info</line>
+  <line>Command: ./leaky</line>
+</preamble>
+
+<pid>7673</pid>
+<ppid>32361</ppid>
+<tool>memcheck</tool>
+
+<args>
+  <vargv>
+    <exe>/usr/bin/valgrind.bin</exe>
+    <arg>--suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp</arg>
+    <arg>--xml-file=/tmp/t</arg>
+    <arg>--xml=yes</arg>
+  </vargv>
+  <argv>
+    <exe>./leaky</exe>
+  </argv>
+</args>
+
+<status>
+  <state>RUNNING</state>
+  <time>00:00:00:00.039 </time>
+</status>
+
+<error>
+  <unique>0x4</unique>
+  <tid>1</tid>
+  <kind>UninitValue</kind>
+  <what>Use of uninitialised value of size 8</what>
+  <stack>
+    <frame>
+      <ip>0x4E6A76B</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>_itoa_word</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>_itoa.c</file>
+      <line>195</line>
+    </frame>
+    <frame>
+      <ip>0x4E6B9B8</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vfprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>vfprintf.c</file>
+      <line>1613</line>
+    </frame>
+    <frame>
+      <ip>0x4E903F1</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vsnprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/libio</dir>
+      <file>vsnprintf.c</file>
+      <line>120</line>
+    </frame>
+    <frame>
+      <ip>0x4E75902</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>snprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>snprintf.c</file>
+      <line>35</line>
+    </frame>
+    <frame>
+      <ip>0x40056D</ip>
+      <obj>/mnt/e4test/src/grindhouse/leaky</obj>
+      <fn>main</fn>
+    </frame>
+  </stack>
+</error>
+
+<error>
+  <unique>0x5</unique>
+  <tid>1</tid>
+  <kind>UninitCondition</kind>
+  <what>Conditional jump or move depends on uninitialised value(s)</what>
+  <stack>
+    <frame>
+      <ip>0x4E6A775</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>_itoa_word</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>_itoa.c</file>
+      <line>195</line>
+    </frame>
+    <frame>
+      <ip>0x4E6B9B8</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vfprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>vfprintf.c</file>
+      <line>1613</line>
+    </frame>
+    <frame>
+      <ip>0x4E903F1</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vsnprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/libio</dir>
+      <file>vsnprintf.c</file>
+      <line>120</line>
+    </frame>
+    <frame>
+      <ip>0x4E75902</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>snprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>snprintf.c</file>
+      <line>35</line>
+    </frame>
+    <frame>
+      <ip>0x40056D</ip>
+      <obj>/mnt/e4test/src/grindhouse/leaky</obj>
+      <fn>main</fn>
+    </frame>
+  </stack>
+</error>
+
+<error>
+  <unique>0x6</unique>
+  <tid>1</tid>
+  <kind>UninitCondition</kind>
+  <what>Conditional jump or move depends on uninitialised value(s)</what>
+  <stack>
+    <frame>
+      <ip>0x4E6D928</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vfprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>vfprintf.c</file>
+      <line>1613</line>
+    </frame>
+    <frame>
+      <ip>0x4E903F1</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vsnprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/libio</dir>
+      <file>vsnprintf.c</file>
+      <line>120</line>
+    </frame>
+    <frame>
+      <ip>0x4E75902</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>snprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>snprintf.c</file>
+      <line>35</line>
+    </frame>
+    <frame>
+      <ip>0x40056D</ip>
+      <obj>/mnt/e4test/src/grindhouse/leaky</obj>
+      <fn>main</fn>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>snprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>snprintf.c</file>
+      <line>35</line>
+    </frame>
+    <frame>
+      <ip>0x40056D</ip>
+      <obj>/mnt/e4test/src/grindhouse/leaky</obj>
+      <fn>main</fn>
+  <tid>1</tid>
+  <kind>UninitCondition</kind>
+  <what>Conditional jump or move depends on uninitialised value(s)</what>
+  <stack>
+    <frame>
+      <ip>0x4E6D928</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vfprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>vfprintf.c</file>
+      <line>1613</line>
+    </frame>
+    <frame>
+      <ip>0x4E903F1</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vsnprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/libio</dir>
+      <file>vsnprintf.c</file>
+      <line>120</line>
+    </frame>
+    <frame>
+      <ip>0x4E75902</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>snprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>snprintf.c</file>
+      <line>35</line>
+    </frame>
+    <frame>
+      <ip>0x40056D</ip>
+      <obj>/mnt/e4test/src/grindhouse/leaky</obj>
+      <fn>main</fn>
+    </frame>
+  </stack>
+</error>
+
+<error>
+  <unique>0x7</unique>
+  <tid>1</tid>
+  <kind>UninitCondition</kind>
+  <what>Conditional jump or move depends on uninitialised value(s)</what>
+  <stack>
+    <frame>
+      <ip>0x4E6BAA6</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vfprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>vfprintf.c</file>
+      <line>1613</line>
+    </frame>
+    <frame>
+      <ip>0x4E903F1</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>vsnprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/libio</dir>
+      <file>vsnprintf.c</file>
+      <line>120</line>
+    </frame>
+    <frame>
+      <ip>0x4E75902</ip>
+      <obj>/lib/libc-2.11.2.so</obj>
+      <fn>snprintf</fn>
+      <dir>/home/aurel32/eglibc/eglibc-2.11.2/stdio-common</dir>
+      <file>snprintf.c</file>
+      <line>35</line>
+    </frame>
+    <frame>
+      <ip>0x40056D</ip>
+      <obj>/mnt/e4test/src/grindhouse/leaky</obj>
+      <fn>main</fn>
+    </frame>
+  </stack>
+</error>
+
+
+<status>
+  <state>FINISHED</state>
+  <time>00:00:00:00.364 </time>
+</status>
+
+<error>
+  <unique>0x8</unique>
+  <tid>1</tid>
+  <kind>Leak_DefinitelyLost</kind>
+  <xwhat>
+    <text>100 bytes in 1 blocks are definitely lost in loss record 1 of 1</text>
+    <leakedbytes>100</leakedbytes>
+    <leakedblocks>1</leakedblocks>
+  </xwhat>
+  <stack>
+    <frame>
+      <ip>0x4C244E8</ip>
+      <obj>/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so</obj>
+      <fn>malloc</fn>
+      <dir>/build/buildd-valgrind_3.6.0~svn11254+nmu1-amd64-08RYEm/valgrind-3.6.0~svn11254+nmu1/coregrind/m_replacemalloc</dir>
+      <file>vg_replace_malloc.c</file>
+      <line>236</line>
+    </frame>
+    <frame>
+      <ip>0x400548</ip>
+      <obj>/mnt/e4test/src/grindhouse/leaky</obj>
+      <fn>main</fn>
+    </frame>
+  </stack>
+</error>
+`
+
+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 (file)
index 0000000..5fefa0c
--- /dev/null
+++ b/leaky.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+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 (file)
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=<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)
+}