Skip to content
Permalink
Browse files

decomp: update to latest gonum/gonum API

  • Loading branch information...
mewmew committed Nov 15, 2018
1 parent 4db501e commit 0d8260c1ad3c24cecbba58f3fd30423651f6f884
Showing with 77 additions and 51 deletions.
  1. +1 −0 .gitignore
  2. +6 −2 cfa/cfa.go
  3. +7 −5 cfa/if.go
  4. +9 −7 cfa/if_else.go
  5. +9 −6 cfa/if_return.go
  6. +6 −4 cfa/post_loop.go
  7. +7 −5 cfa/pre_loop.go
  8. +6 −4 cfa/seq.go
  9. +1 −1 cmd/ll2dot/main.go
  10. +8 −6 cmd/ll2go/main.go
  11. +7 −5 cmd/restructure/main.go
  12. +7 −5 go.mod
  13. +3 −1 graph/cfg/decode.go
@@ -5,3 +5,4 @@
*.xcf
*.exe
vendor
go.sum
@@ -77,7 +77,9 @@ func Merge(g *cfg.Graph, prim *primitive.Primitive) error {
p := g.NewNodeWithLabel(fmt.Sprintf("prim_node_of_%s", entryLabel))

// Connect incoming edges to entry.
for _, from := range g.To(entry.ID()) {
fromNodes := g.To(entry.ID())
for fromNodes.Next() {
from := fromNodes.Node()
e := g.Edge(from.ID(), entry.ID())
var label string
if e, ok := e.(*cfg.Edge); ok {
@@ -87,7 +89,9 @@ func Merge(g *cfg.Graph, prim *primitive.Primitive) error {
}

// Connect outgoing edges from exit.
for _, to := range g.From(exit.ID()) {
toNodes := g.From(exit.ID())
for toNodes.Next() {
to := toNodes.Node()
e := g.Edge(exit.ID(), to.ID())
var label string
if e, ok := e.(*cfg.Edge); ok {
@@ -72,9 +72,11 @@ digraph if {
// and a boolean indicating if such a primitive was found.
func FindIf(g graph.Directed, dom cfg.DominatorTree) (prim If, ok bool) {
// Range through cond node candidates.
for _, cond := range g.Nodes() {
condNodes := g.Nodes()
for condNodes.Next() {
cond := condNodes.Node()
// Verify that cond has two successors (body and exit).
condSuccs := g.From(cond.ID())
condSuccs := graph.NodesOf(g.From(cond.ID()))
if len(condSuccs) != 2 {
continue
}
@@ -114,18 +116,18 @@ func (prim If) IsValid(g graph.Directed, dom cfg.DominatorTree) bool {

// Verify that cond has two successors (body and exit).
condSuccs := g.From(cond.ID())
if len(condSuccs) != 2 || !g.HasEdgeFromTo(cond.ID(), body.ID()) || !g.HasEdgeFromTo(cond.ID(), exit.ID()) {
if condSuccs.Len() != 2 || !g.HasEdgeFromTo(cond.ID(), body.ID()) || !g.HasEdgeFromTo(cond.ID(), exit.ID()) {
return false
}

// Verify that body has one predecessor (cond) and one successor (exit).
bodyPreds := g.To(body.ID())
bodySuccs := g.From(body.ID())
if len(bodyPreds) != 1 || len(bodySuccs) != 1 || !g.HasEdgeFromTo(body.ID(), exit.ID()) {
if bodyPreds.Len() != 1 || bodySuccs.Len() != 1 || !g.HasEdgeFromTo(body.ID(), exit.ID()) {
return false
}

// Verify that exit has two predecessors (cond and body).
exitPreds := g.To(exit.ID())
return len(exitPreds) == 2
return exitPreds.Len() == 2
}
@@ -80,9 +80,11 @@ digraph if_else {
// g, and a boolean indicating if such a primitive was found.
func FindIfElse(g graph.Directed, dom cfg.DominatorTree) (prim IfElse, ok bool) {
// Range through cond node candidates.
for _, cond := range g.Nodes() {
condNodes := g.Nodes()
for condNodes.Next() {
cond := condNodes.Node()
// Verify that cond has two successors (body_true and body_false).
condSuccs := g.From(cond.ID())
condSuccs := graph.NodesOf(g.From(cond.ID()))
if len(condSuccs) != 2 {
continue
}
@@ -92,7 +94,7 @@ func FindIfElse(g graph.Directed, dom cfg.DominatorTree) (prim IfElse, ok bool)
prim.BodyTrue, prim.BodyFalse = condSuccs[0], condSuccs[1]

// Verify that body_true has one successor (exit).
bodyTrueSuccs := g.From(prim.BodyTrue.ID())
bodyTrueSuccs := graph.NodesOf(g.From(prim.BodyTrue.ID()))
if len(bodyTrueSuccs) != 1 {
continue
}
@@ -125,25 +127,25 @@ func (prim IfElse) IsValid(g graph.Directed, dom cfg.DominatorTree) bool {

// Verify that cond has two successors (body_true and body_false).
condSuccs := g.From(cond.ID())
if len(condSuccs) != 2 || !g.HasEdgeFromTo(cond.ID(), bodyTrue.ID()) || !g.HasEdgeFromTo(cond.ID(), bodyFalse.ID()) {
if condSuccs.Len() != 2 || !g.HasEdgeFromTo(cond.ID(), bodyTrue.ID()) || !g.HasEdgeFromTo(cond.ID(), bodyFalse.ID()) {
return false
}

// Verify that body_true has one predecessor (cond) and one successor (exit).
bodyTrueSuccs := g.From(bodyTrue.ID())
bodyTruePreds := g.To(bodyTrue.ID())
if len(bodyTruePreds) != 1 || len(bodyTrueSuccs) != 1 || !g.HasEdgeFromTo(bodyTrue.ID(), exit.ID()) {
if bodyTruePreds.Len() != 1 || bodyTrueSuccs.Len() != 1 || !g.HasEdgeFromTo(bodyTrue.ID(), exit.ID()) {
return false
}

// Verify that body_false has one predecessor (cond) and one successor (exit).
bodyFalseSuccs := g.From(bodyFalse.ID())
bodyFalsePreds := g.To(bodyFalse.ID())
if len(bodyFalsePreds) != 1 || len(bodyFalseSuccs) != 1 || !g.HasEdgeFromTo(bodyFalse.ID(), exit.ID()) {
if bodyFalsePreds.Len() != 1 || bodyFalseSuccs.Len() != 1 || !g.HasEdgeFromTo(bodyFalse.ID(), exit.ID()) {
return false
}

// Verify that exit has two predecessor (body_true and body_false).
exitPreds := g.To(exit.ID())
return len(exitPreds) == 2
return exitPreds.Len() == 2
}
@@ -72,9 +72,11 @@ digraph if_return {
// found.
func FindIfReturn(g graph.Directed, dom cfg.DominatorTree) (prim IfReturn, ok bool) {
// Range through cond node candidates.
for _, cond := range g.Nodes() {
condNodes := g.Nodes()
for condNodes.Next() {
cond := condNodes.Node()
// Verify that cond has two successors (body and exit).
condSuccs := g.From(cond.ID())
condSuccs := graph.NodesOf(g.From(cond.ID()))
if len(condSuccs) != 2 {
continue
}
@@ -114,20 +116,20 @@ func (prim IfReturn) IsValid(g graph.Directed, dom cfg.DominatorTree) bool {

// Verify that cond has two successors (body and exit).
condSuccs := g.From(cond.ID())
if len(condSuccs) != 2 || !g.HasEdgeFromTo(cond.ID(), body.ID()) || !g.HasEdgeFromTo(cond.ID(), exit.ID()) {
if condSuccs.Len() != 2 || !g.HasEdgeFromTo(cond.ID(), body.ID()) || !g.HasEdgeFromTo(cond.ID(), exit.ID()) {
return false
}

// Verify that body has one predecessor (cond) and zero successors.
bodyPreds := g.To(body.ID())
bodySuccs := g.From(body.ID())
if len(bodyPreds) != 1 || len(bodySuccs) != 0 {
if bodyPreds.Len() != 1 || bodySuccs.Len() != 0 {
return false
}

// Verify that exit has one predecessor (cond).
exitPreds := g.To(exit.ID())
if len(exitPreds) != 1 {
if exitPreds.Len() != 1 {
return false
}

@@ -142,7 +144,8 @@ func (prim IfReturn) IsValid(g graph.Directed, dom cfg.DominatorTree) bool {
// ↖ ↓
// A
condPreds := g.To(cond.ID())
for _, pred := range condPreds {
for condPreds.Next() {
pred := condPreds.Node()
if dom.Dominates(cond, pred) {
return false
}
@@ -65,9 +65,11 @@ digraph post_loop {
// boolean indicating if such a primitive was found.
func FindPostLoop(g graph.Directed, dom cfg.DominatorTree) (prim PostLoop, ok bool) {
// Range through cond node candidates.
for _, cond := range g.Nodes() {
condNodes := g.Nodes()
for condNodes.Next() {
cond := condNodes.Node()
// Verify that cond has two successors (cond and exit).
condSuccs := g.From(cond.ID())
condSuccs := graph.NodesOf(g.From(cond.ID()))
if len(condSuccs) != 2 {
continue
}
@@ -106,11 +108,11 @@ func (prim PostLoop) IsValid(g graph.Directed, dom cfg.DominatorTree) bool {

// Verify that cond has two successors (cond and exit).
condSuccs := g.From(cond.ID())
if len(condSuccs) != 2 || !g.HasEdgeFromTo(cond.ID(), cond.ID()) || !g.HasEdgeFromTo(cond.ID(), exit.ID()) {
if condSuccs.Len() != 2 || !g.HasEdgeFromTo(cond.ID(), cond.ID()) || !g.HasEdgeFromTo(cond.ID(), exit.ID()) {
return false
}

// Verify that exit has one predecessor (cond).
exitPreds := g.To(exit.ID())
return len(exitPreds) == 1
return exitPreds.Len() == 1
}
@@ -72,9 +72,11 @@ digraph pre_loop {
// boolean indicating if such a primitive was found.
func FindPreLoop(g graph.Directed, dom cfg.DominatorTree) (prim PreLoop, ok bool) {
// Range through cond node candidates.
for _, cond := range g.Nodes() {
condNodes := g.Nodes()
for condNodes.Next() {
cond := condNodes.Node()
// Verify that cond has two successors (body and exit).
condSuccs := g.From(cond.ID())
condSuccs := graph.NodesOf(g.From(cond.ID()))
if len(condSuccs) != 2 {
continue
}
@@ -114,18 +116,18 @@ func (prim PreLoop) IsValid(g graph.Directed, dom cfg.DominatorTree) bool {

// Verify that cond has two successors (body and exit).
condSuccs := g.From(cond.ID())
if len(condSuccs) != 2 || !g.HasEdgeFromTo(cond.ID(), body.ID()) || !g.HasEdgeFromTo(cond.ID(), exit.ID()) {
if condSuccs.Len() != 2 || !g.HasEdgeFromTo(cond.ID(), body.ID()) || !g.HasEdgeFromTo(cond.ID(), exit.ID()) {
return false
}

// Verify that body has one predecessor (cond) and one successor (cond).
bodyPreds := g.To(body.ID())
bodySuccs := g.From(body.ID())
if len(bodyPreds) != 1 || len(bodySuccs) != 1 || !g.HasEdgeFromTo(body.ID(), cond.ID()) {
if bodyPreds.Len() != 1 || bodySuccs.Len() != 1 || !g.HasEdgeFromTo(body.ID(), cond.ID()) {
return false
}

// Verify that exit has one predecessor (cond).
exitPreds := g.To(exit.ID())
return len(exitPreds) == 1
return exitPreds.Len() == 1
}
@@ -62,9 +62,11 @@ digraph seq {
// and a boolean indicating if such a primitive was found.
func FindSeq(g graph.Directed, dom cfg.DominatorTree) (prim Seq, ok bool) {
// Range through entry node candidates.
for _, entry := range g.Nodes() {
entryNodes := g.Nodes()
for entryNodes.Next() {
entry := entryNodes.Node()
// Verify that entry has one successor (exit).
entrySuccs := g.From(entry.ID())
entrySuccs := graph.NodesOf(g.From(entry.ID()))
if len(entrySuccs) != 1 {
continue
}
@@ -96,11 +98,11 @@ func (prim Seq) IsValid(g graph.Directed, dom cfg.DominatorTree) bool {

// Verify that entry has one successor (exit).
entrySuccs := g.From(entry.ID())
if len(entrySuccs) != 1 || !g.HasEdgeFromTo(entry.ID(), exit.ID()) {
if entrySuccs.Len() != 1 || !g.HasEdgeFromTo(entry.ID(), exit.ID()) {
return false
}

// Verify that exit has one predecessor (entry).
exitPreds := g.To(exit.ID())
return len(exitPreds) == 1
return exitPreds.Len() == 1
}
@@ -180,7 +180,7 @@ func createDotDir(llPath string, force bool) (string, error) {
// foo_graphs/bar.dot
// foo_graphs/baz.dot
func storeCFG(g graph.Directed, funcName, dotDir string, img bool) error {
buf, err := dot.Marshal(g, fmt.Sprintf("%q", funcName), "", "\t", false)
buf, err := dot.Marshal(g, fmt.Sprintf("%q", funcName), "", "\t")
if err != nil {
return errors.WithStack(err)
}
@@ -162,7 +162,7 @@ func ll2go(llPath string, funcNames map[string]bool) (*ast.File, error) {
return nil, errors.WithStack(err)
}
}
dbg.Printf("decompiling function %q.", f.Name)
dbg.Printf("decompiling function %q.", f.Ident())
fn, err := d.funcDecl(f, prims)
if err != nil {
return nil, errors.WithStack(err)
@@ -579,7 +579,7 @@ func parsePrims(srcName string, f *ir.Function) ([]*primitive.Primitive, error)
prims, err := genPrims(f)
if err != nil {
if errors.Cause(err) == ErrIncomplete {
dbg.Printf("WARNING: incomplete control flow recovery of %q", f.Name)
dbg.Printf("WARNING: incomplete control flow recovery of %q", f.Ident())
} else {
return nil, errors.WithStack(err)
}
@@ -609,9 +609,11 @@ var ErrIncomplete = goerrors.New("incomplete control flow recovery")
// edges.
func locateEntryNode(g *cfg.Graph) (graph.Node, error) {
var entry graph.Node
for _, n := range g.Nodes() {
nodes := g.Nodes()
for nodes.Next() {
n := nodes.Node()
preds := g.To(n.ID())
if len(preds) == 0 {
if preds.Len() == 0 {
if entry != nil {
return nil, errors.Errorf("more than one candidate for the entry node located; prev %q, new %q", label(entry), label(n))
}
@@ -633,7 +635,7 @@ func genPrims(f *ir.Function) ([]*primitive.Primitive, error) {
log.Fatalf("%+v", err)
}
var prims []*primitive.Primitive
for len(g.Nodes()) > 1 {
for g.Nodes().Len() > 1 {
// Locate primitive.
dom := cfg.NewDom(g, entry)
prim, err := cfa.FindPrim(g, dom)
@@ -647,7 +649,7 @@ func genPrims(f *ir.Function) ([]*primitive.Primitive, error) {
}
// Handle special case where entry node has been replaced by primitive
// node.
if !g.Has(entry.ID()) {
if g.Node(entry.ID()) == nil {
var ok bool
entry, ok = g.NodeByLabel(prim.Entry)
if !ok {
@@ -149,9 +149,11 @@ func locateEntryNode(g *cfg.Graph, entryLabel string) (graph.Node, error) {
return entry, nil
}
var entry graph.Node
for _, n := range g.Nodes() {
nodes := g.Nodes()
for nodes.Next() {
n := nodes.Node()
preds := g.To(n.ID())
if len(preds) == 0 {
if preds.Len() == 0 {
if entry != nil {
return nil, errors.Errorf("more than one candidate for the entry node located; prev %q, new %q", label(entry), label(n))
}
@@ -177,7 +179,7 @@ var ErrIncomplete = goerrors.New("incomplete control flow recovery")
func restructure(g *cfg.Graph, entry graph.Node, steps bool, name string) ([]*primitive.Primitive, error) {
prims := make([]*primitive.Primitive, 0)
// Locate control flow primitives.
for step := 1; len(g.Nodes()) > 1; step++ {
for step := 1; g.Nodes().Len() > 1; step++ {
// Locate primitive.
dom := cfg.NewDom(g, entry)
prim, err := cfa.FindPrim(g, dom)
@@ -204,7 +206,7 @@ func restructure(g *cfg.Graph, entry graph.Node, steps bool, name string) ([]*pr
}
// Handle special case where entry node has been replaced by primitive
// node.
if !g.Has(entry.ID()) {
if g.Node(entry.ID()) == nil {
var ok bool
entry, ok = g.NodeByLabel(prim.Entry)
if !ok {
@@ -235,7 +237,7 @@ func storeStep(g *cfg.Graph, name, path string, highlight []string) error {
n.Attrs["style"] = "filled"
n.Attrs["fillcolor"] = "red"
}
buf, err := dot.Marshal(g, strconv.Quote(name), "", "\t", false)
buf, err := dot.Marshal(g, strconv.Quote(name), "", "\t")
if err != nil {
return errors.WithStack(err)
}
12 go.mod
@@ -2,11 +2,13 @@ module github.com/decomp/decomp

require (
bitbucket.org/zombiezen/cardcpx v0.0.0-20150417151802-902f68ff43ef
github.com/graphism/exp v0.0.0-20180515191528-78b6f6b90bd7
github.com/graphism/exp v0.0.0-20181113033608-bebe8efb45ee
github.com/graphism/simple v0.0.0-20180515061654-415a775f75dc
github.com/llir/llvm v0.0.0-20180307193049-784d18aa9fbe
github.com/mewkiz/pkg v0.0.0-20170428133157-c19a6f9fa6f8
github.com/kr/pty v1.1.3 // indirect
github.com/llir/llvm v0.2.1
github.com/mewkiz/pkg v0.0.0-20181108225906-b4dee0c4e703
github.com/pkg/errors v0.8.0
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de
gonum.org/v1/gonum v0.0.0-20180523214355-f5d91d72f89a
golang.org/x/exp v0.0.0-20181112044915-a3060d491354
golang.org/x/tools v0.0.0-20181113033837-a8570e12b662 // indirect
gonum.org/v1/gonum v0.0.0-20181112092319-eb6a40d81aaf
)
@@ -22,7 +22,9 @@ func ParseFile(path string) (*Graph, error) {
if err := dot.Unmarshal(data, g); err != nil {
return nil, errors.WithStack(err)
}
for _, n := range g.Nodes() {
nodes := g.Nodes()
for nodes.Next() {
n := nodes.Node()
if n, ok := n.(*Node); ok {
if n.entry {
// Store entry node.

0 comments on commit 0d8260c

Please sign in to comment.
You can’t perform that action at this time.