justinstenning / SharpDisasm

SharpDisasm - x86 / x86-64 disassembler for .NET
https://www.nuget.org/packages/SharpDisasm
Other
212 stars 39 forks source link

Interfacing 'Instruction' class #19

Closed shlomoartsi closed 6 years ago

shlomoartsi commented 6 years ago

A support is added to generate a different Instruction class (ie MyInstruction). For that we define an IInstruction interface for Instruction class. in addition a IInstructionFactory is injected to the ctor of Disassembler in order to generate a different class implementing IInstruction . The backward compatibility is maintained, and if no implementation of IInstructionFactory is injected than an InstructionFactory class that generate the Instruction class is used.

I've used your project for implementing a binary obfuscation project. For that i needed to add more info for Instruction class, such as previous and next instruction fields. I didn't want to add these fields on the project itself, but on my custom class that defines an instruction. I've found that the most structured way for doing this is to change the project to use interface of IInstruction instead of actual class of Instruction , and to use dependency injection for factory of IInstruction implementation instead of using "new Instruction()" where needed. An example for the dependency injection is the Disassembler ctor. This injection allows the consumer of the project to have an actual control of the creation of Instruction class (and by the way promote the testablity of Disassembler class):

public Disassembler(IAssemblyCode code, ArchitectureMode architecture, ulong address = 0x0, bool copyBinaryToInstruction = false, Vendor vendor = Vendor.Any, IInstructionFactory instructionFactory = null) { ... if (instructionFactory == null) { this.InstructionFactory = new InstructionFactory(); } else { this.InstructionFactory = instructionFactory; } ... }

using the factory: _public IInstruction NextInstruction() { int length = 0; if ((length = Udis86.udis86.ud_disassemble(ref u)) > 0) { var instruction = InstructionFactory.Create(ref _u, CopyBinaryToInstruction); if (!instruction.Error) { BytesDecoded += length; } return instruction; } return null; }