in cmd/viewcore/main.go [540:605]
func runObjgraph(cmd *cobra.Command, args []string) {
_, c, err := readCore()
if err != nil {
exitf("%v\n", err)
}
fname := args[0]
// Dump object graph to output file.
w, err := os.Create(fname)
if err != nil {
panic(err)
}
fmt.Fprintf(w, "digraph {\n")
for k, r := range c.Globals() {
printed := false
c.ForEachRootPtr(r, func(i int64, y gocore.Object, j int64) bool {
if !printed {
fmt.Fprintf(w, "r%d [label=\"%s\n%s\",shape=hexagon]\n", k, r.Name, r.Type)
printed = true
}
fmt.Fprintf(w, "r%d -> o%x [label=\"%s\"", k, c.Addr(y), typeFieldName(r.Type, i))
if j != 0 {
fmt.Fprintf(w, " ,headlabel=\"+%d\"", j)
}
fmt.Fprintf(w, "]\n")
return true
})
}
for _, g := range c.Goroutines() {
last := fmt.Sprintf("o%x", g.Addr())
for _, f := range g.Frames() {
frame := fmt.Sprintf("f%x", f.Max())
fmt.Fprintf(w, "%s [label=\"%s\",shape=rectangle]\n", frame, f.Func().Name())
fmt.Fprintf(w, "%s -> %s [style=dotted]\n", last, frame)
last = frame
for _, r := range f.Roots() {
c.ForEachRootPtr(r, func(i int64, y gocore.Object, j int64) bool {
fmt.Fprintf(w, "%s -> o%x [label=\"%s%s\"", frame, c.Addr(y), r.Name, typeFieldName(r.Type, i))
if j != 0 {
fmt.Fprintf(w, " ,headlabel=\"+%d\"", j)
}
fmt.Fprintf(w, "]\n")
return true
})
}
}
}
c.ForEachObject(func(x gocore.Object) bool {
addr := c.Addr(x)
size := c.Size(x)
fmt.Fprintf(w, "o%x [label=\"%s\\n%d\"]\n", addr, typeName(c, x), size)
c.ForEachPtr(x, func(i int64, y gocore.Object, j int64) bool {
fmt.Fprintf(w, "o%x -> o%x [label=\"%s\"", addr, c.Addr(y), fieldName(c, x, i))
if j != 0 {
fmt.Fprintf(w, ",headlabel=\"+%d\"", j)
}
fmt.Fprintf(w, "]\n")
return true
})
return true
})
fmt.Fprintf(w, "}")
w.Close()
fmt.Fprintf(os.Stderr, "wrote the object graph to %q\n", fname)
}