github.com/decomp/exp@v0.0.0-20210624183419-6d058f5e1da6/cmd/bin2c/func.go (about) 1 package main 2 3 import ( 4 "fmt" 5 dbg "fmt" 6 "go/ast" 7 "go/printer" 8 "go/token" 9 "os" 10 11 "github.com/mewkiz/pkg/errutil" 12 "golang.org/x/arch/x86/x86asm" 13 ) 14 15 // parseFunc parses the given function and returns a corresponding Go function. 16 func parseFunc(text []byte, offset int) (*ast.FuncDecl, error) { 17 fn := &ast.FuncDecl{ 18 Name: getLabel("sub", offset), 19 Type: &ast.FuncType{}, 20 Body: new(ast.BlockStmt), 21 } 22 23 for { 24 // Decode instruction. 25 inst, err := x86asm.Decode(text[offset:], 32) 26 if err != nil { 27 return nil, errutil.Err(err) 28 } 29 dbg.Println("==================================") 30 dbg.Println("inst:", inst) 31 32 // Parse instruction. 33 stmt, err := parseInst(inst, offset) 34 if err != nil { 35 return nil, errutil.Err(err) 36 } 37 if stmt != nil { 38 // Access the underlying statement list of the block statement. 39 if block, ok := stmt.(*ast.BlockStmt); ok { 40 label := getLabel("loc", offset) 41 stmt = block.List[0] 42 stmt = &ast.LabeledStmt{Label: label, Stmt: stmt} 43 block.List[0] = stmt 44 fn.Body.List = append(fn.Body.List, block.List...) 45 for _, stmt := range block.List { 46 dbg.Println("stmt:", stmt) 47 //ast.Print(token.NewFileSet(), stmt) 48 printer.Fprint(os.Stderr, token.NewFileSet(), stmt) 49 dbg.Println() 50 } 51 } else { 52 label := getLabel("loc", offset) 53 stmt = &ast.LabeledStmt{Label: label, Stmt: stmt} 54 fn.Body.List = append(fn.Body.List, stmt) 55 dbg.Println("stmt:", stmt) 56 //ast.Print(token.NewFileSet(), stmt) 57 printer.Fprint(os.Stderr, token.NewFileSet(), stmt) 58 dbg.Println() 59 } 60 } 61 dbg.Println() 62 63 // Next. 64 offset += inst.Len 65 if inst.Op == x86asm.RET { 66 break 67 } 68 } 69 70 return fn, nil 71 } 72 73 // labels maps from offset to label identifiers. 74 var labels = map[int]*ast.Ident{} 75 76 // getLabel returns the label with the given prefix and at the given offset. 77 func getLabel(prefix string, offset int) *ast.Ident { 78 if label, ok := labels[offset]; ok { 79 return label 80 } 81 addr := baseAddr + offset 82 name := fmt.Sprintf("%s_%X", prefix, addr) 83 label := ast.NewIdent(name) 84 labels[offset] = label 85 return label 86 }