1 /// Idiomatic lifting of $(LINK2 http://www.capstone-engine.org, Capstone)'s C API to D 2 module capstone.api; 3 4 import std.typecons: BitFlags, Yes; 5 6 import capstone.internal; 7 import capstone.capstone: Capstone; 8 9 /// Architecture type 10 enum Arch{ 11 arm = 0, /// ARM architecture (including Thumb, Thumb-2) 12 arm64, /// ARM-64 (also called AArch64) 13 mips, /// Mips architecture 14 x86, /// X86 architecture (including x86 & x86-64) 15 ppc, /// PowerPC architecture 16 sparc, /// Sparc architecture 17 sysz, /// SystemZ architecture 18 xcore, /// XCore architecture 19 m68k, /// 68K architecture 20 tms320c64x, /// TMS320C64x architecture 21 m680x, /// 680X architecture 22 evm, /// Ethereum architecture 23 } 24 25 /// The support options that Capstone can be compiled with 26 enum SupportQuery { 27 arm = 0, /// Support for ARM architecture (including Thumb, Thumb-2) 28 arm64, /// Support for ARM-64 (also called AArch64) 29 mips, /// Support for Mips architecture 30 x86, /// Support for X86 architecture (including x86 & x86-64) 31 ppc, /// Support for PowerPC architecture 32 sparc, /// Support for Sparc architecture 33 sysz, /// Support for SystemZ architecture 34 xcore, /// Support for XCore architecture 35 m68k, /// 68K architecture 36 tms320c64x, /// TMS320C64x architecture 37 m680x, /// 680X architecture 38 evm, /// Ethereum architecture 39 all = 0xFFFF, /// Supports all architectures 40 diet, /// Compiled in diet mode, i.e. missing less relevant data fields 41 x86reduce /// Compiled in X86-reduce mode, i.e. missing less relevant data fields and exotic X86 instruction sets 42 } 43 44 /// Mode type 45 enum Mode { 46 littleEndian = 0, /// Little-endian mode (default mode) 47 arm = 0, /// 32-bit ARM 48 bit16 = 1 << 1, /// 16-bit mode (X86) 49 bit32 = 1 << 2, /// 32-bit mode (X86) 50 bit64 = 1 << 3, /// 64-bit mode (X86, PPC) 51 armThumb = 1 << 4, /// ARM's Thumb mode, including Thumb-2 52 armCortexM = 1 << 5, /// ARM's Cortex-M series 53 armV8 = 1 << 6, /// ARMv8 A32 encodings for ARM 54 mipsMicro = 1 << 4, /// MicroMips mode (MIPS) 55 mips3 = 1 << 5, /// Mips III ISA 56 mips32r6 = 1 << 6, /// Mips32r6 ISA 57 mips2 = 1 << 7, /// Mips II ISA 58 sparcV9 = 1 << 4, /// SparcV9 mode (Sparc) 59 qpx = 1 << 4, /// Quad Processing eXtensions mode (PPC) 60 m68k_000 = 1 << 1, /// M68K 68000 mode 61 m68k_010 = 1 << 2, /// M68K 68010 mode 62 m68k_020 = 1 << 3, /// M68K 68020 mode 63 m68k_030 = 1 << 4, /// M68K 68030 mode 64 m68k_040 = 1 << 5, /// M68K 68040 mode 65 m68k_060 = 1 << 6, /// M68K 68060 mode 66 bigEndian = 1 << 31, /// Big-endian mode 67 mips32 = bit32, /// Mips32 ISA (Mips) 68 mips64 = bit64, /// Mips64 ISA (Mips) 69 m680x_6301 = 1 << 1, /// M680X Hitachi 6301,6303 mode 70 m680x_6309 = 1 << 2, /// M680X Hitachi 6309 mode 71 m680x_6800 = 1 << 3, /// M680X Motorola 6800,6802 mode 72 m680x_6801 = 1 << 4, /// M680X Motorola 6801,6803 mode 73 m680x_6805 = 1 << 5, /// M680X Motorola/Freescale 6805 mode 74 m680x_6808 = 1 << 6, /// M680X Motorola/Freescale/NXP 68HC08 mode 75 m680x_6809 = 1 << 7, /// M680X Motorola 6809 mode 76 m680x_6811 = 1 << 8, /// M680X Motorola/Freescale/NXP 68HC11 mode 77 m680x_cpu12 = 1 << 9, /// M680X Motorola/Freescale/NXP CPU12 78 m680x_hcs08 = 1 << 10, /// M680X Freescale/NXP HCS08 mode 79 } 80 /** Alias for combination of several modes 81 82 Example: 83 --- 84 auto flags = ModeFlags(Mode.arm + Mode.armV8); 85 --- 86 */ 87 alias ModeFlags = BitFlags!(Mode, Yes.unsafe); 88 89 90 /// Disassembly syntax variants 91 enum Syntax { 92 systemDefault = 0, /// System's default syntax 93 intel, /// X86 Intel syntax - default on X86 94 att, /// X86 AT&T syntax 95 noregname, /// Prints register name with only number 96 masm, /// X86 Intel Masm syntax 97 } 98 99 /** User-defined callback function type for SKIPDATA mode of operation 100 101 The first parameter is the input buffer containing code to be disassembled, 102 while the second one holds the position of the currently-examined byte in this buffer. 103 104 Returns: The number of bytes to skip, or 0 to immediately stop disassembling 105 106 Example: 107 --- 108 size_t callback(in ubyte[] code, size_t offset) { 109 return 2; // Always skip 2 bytes when encountering uninterpretable instructions 110 } 111 --- 112 See `Capstone.setupSkipdata` documentation for full sample code demonstrating this functionality. 113 */ 114 alias Callback = size_t delegate(in ubyte[] code, size_t offset) nothrow @nogc; 115 116 // This trampoline is the ugly C-lang callback (calling D in turn) 117 package extern(C) size_t cCallback(const(ubyte)* code, size_t code_size, size_t offset, void* userData) nothrow @nogc{ 118 auto slice = code[0..code_size]; 119 120 // Call the nice d-lang callback 121 auto dCallback = *cast(Callback*)userData; 122 auto res = dCallback(slice, offset); 123 return res; 124 } 125 126 /// Version consisting of major and minor numbers 127 struct Version{ 128 int major; /// Major version number 129 int minor; /// Minor version number 130 131 /// Textual representation 132 string toString() const { 133 import std.format: format; 134 return "%s.%s".format(major, minor); 135 } 136 } 137 138 /// Determines the `Version` supported by these bindings 139 auto versionOfBindings() { 140 return Version(CS_API_MAJOR, CS_API_MINOR); 141 } 142 143 /// Determines the `Version` supported by the installed library 144 auto versionOfLibrary() { 145 int major, minor; 146 cs_version(&major, &minor); 147 return Version(major, minor); 148 } 149 /// 150 unittest{ 151 import std.format: format; 152 const libVer = versionOfLibrary; 153 const bindVer = versionOfBindings; 154 assert(libVer == bindVer, "API version mismatch between library (%s) and bindings (%s)".format(libVer, bindVer)); 155 } 156 157 /** Indicates whether the installed library was compiled in $(LINK2 http://www.capstone-engine.org/diet.html, diet mode) 158 159 Convenience functionality which is also available via `supports`. 160 */ 161 bool diet(){ 162 return supports(SupportQuery.diet); 163 } 164 165 /** Indicates whether an architecture or particular option is supported by the installed Capstone library 166 167 Params: 168 query = The `SupportQuery` to issue to the library 169 170 Returns: True if the requested option is supported 171 172 Example: 173 --- 174 // Query installed Capstone library for supported options 175 foreach(query; EnumMembers!SupportQuery) 176 writefln!"%-10s: %s"(query, supports(query)); 177 --- 178 */ 179 bool supports(in SupportQuery query){ 180 return cs_support(query); 181 } 182 183 /// Common instruction operand access types - to be consistent across all architectures. 184 enum AccessType { 185 invalid = 0, /// Uninitialized/invalid access type. 186 read = 1 << 0, /// Operand read from memory or register. 187 write = 1 << 1, /// Operand write to memory or register. 188 } 189 /** Alias for combination of several flags 190 191 Example: 192 --- 193 auto flags = AccessFlags(AccessType.read | AccessType.write); 194 --- 195 */ 196 alias AccessFlags = BitFlags!AccessType; 197 198 // TODO: Rename to capstone? 199 /** Creates a Capstone instance for disassembling code of a specific architecture 200 Params: 201 arch = The architecture to interpret the bytestream for 202 modeFlags = The mode of interpretation 203 204 Example: 205 --- 206 auto cs = create(Arch.x86, ModeFlags(Mode.bit32)); 207 --- 208 */ 209 static Capstone create(Arch arch, ModeFlags modeFlags){ 210 import std.format: format; 211 import capstone.arm: CapstoneArm; 212 import capstone.arm64: CapstoneArm64; 213 import capstone.evm: CapstoneEvm; 214 import capstone.m68k: CapstoneM68k; 215 import capstone.m680x: CapstoneM680x; 216 import capstone.mips: CapstoneMips; 217 import capstone.ppc: CapstonePpc; 218 import capstone.sparc: CapstoneSparc; 219 import capstone.sysz: CapstoneSysz; 220 import capstone.tms320c64x: CapstoneTms320c64x; 221 import capstone.x86: CapstoneX86; 222 import capstone.xcore: CapstoneXCore; 223 import capstone.error: CapstoneException, ErrorCode; 224 225 switch(arch){ 226 case Arch.arm: return new CapstoneArm(modeFlags); 227 case Arch.arm64: return new CapstoneArm64(modeFlags); 228 case Arch.evm: return new CapstoneEvm(modeFlags); 229 case Arch.m68k: return new CapstoneM68k(modeFlags); 230 case Arch.m680x: return new CapstoneM680x(modeFlags); 231 case Arch.mips: return new CapstoneMips(modeFlags); 232 case Arch.ppc: return new CapstonePpc(modeFlags); 233 case Arch.sparc: return new CapstoneSparc(modeFlags); 234 case Arch.sysz: return new CapstoneSysz(modeFlags); 235 case Arch.tms320c64x: return new CapstoneTms320c64x(modeFlags); 236 case Arch.x86: return new CapstoneX86(modeFlags); 237 case Arch.xcore: return new CapstoneXCore(modeFlags); 238 default: 239 throw new CapstoneException("%s architecture not yet supported by bindings".format(arch), ErrorCode.UnsupportedArchitecture); 240 } 241 }