1/* 2 * gomacro - A Go interpreter with Lisp-like macros 3 * 4 * Copyright (C) 2019 Massimiliano Ghilardi 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * 11 * api.go 12 * 13 * Created on Jan 23, 2019 14 * Author Massimiliano Ghilardi 15 */ 16 17package disasm 18 19import ( 20 "testing" 21 22 "github.com/bnagy/gapstone" 23 . "github.com/cosmos72/gomacro/jit" 24 "github.com/cosmos72/gomacro/jit/asm" 25) 26 27type Engine = gapstone.Engine 28 29func NewDisasm(archId ArchId) (Engine, error) { 30 var arch uint = gapstone.CS_ARCH_X86 31 var mode uint = gapstone.CS_MODE_64 32 if archId == ARM64 { 33 arch = gapstone.CS_ARCH_ARM64 34 mode = gapstone.CS_MODE_ARM // | gapstone.CS_MODE_V8 35 } 36 engine, err := gapstone.New( 37 int(arch), 38 mode, 39 ) 40 if err != nil { 41 return engine, err 42 } 43 engine.SetOption(gapstone.CS_OPT_SYNTAX, gapstone.CS_OPT_SYNTAX_ATT) 44 return engine, nil 45} 46 47func Disasm(code asm.MachineCode) ([]gapstone.Instruction, error) { 48 engine, err := NewDisasm(code.ArchId) 49 if err != nil { 50 return nil, err 51 } 52 return engine.Disasm(code.Bytes, 0x10000, 0) 53} 54 55func PrintDisasm(t *testing.T, code asm.MachineCode) { 56 insns, err := Disasm(code) 57 if err != nil { 58 t.Error(err) 59 } else { 60 archId := code.ArchId 61 t.Logf("----- %v -----", archId) 62 for _, insn := range insns { 63 Show(t, archId, insn) 64 } 65 } 66} 67 68func Show(t *testing.T, archId ArchId, insn gapstone.Instruction) { 69 var prefix string 70 bytes := insn.Bytes 71 if archId == ARM64 && len(bytes) == 4 { 72 // print high byte first 73 prefix = "0x" 74 bytes[0], bytes[1], bytes[2], bytes[3] = bytes[3], bytes[2], bytes[1], bytes[0] 75 } 76 t.Logf(" %s%x%s%s\t%s", prefix, bytes, spaces(2*len(insn.Bytes)), insn.Mnemonic, insn.OpStr) 77} 78 79func spaces(n int) string { 80 return " "[n%16:] 81} 82