/// <summary> /// Create a Deferred Instruction Enumerable. /// </summary> /// <param name="disassembler"> /// The disassembler to use. Should not be a null reference. /// </param> /// <param name="code"> /// A collection of bytes representing the binary code to disassemble. Should not be a null reference. /// </param> /// <param name="offset"> /// An offset to start disassembling from. A 0 indicates disassembly should start at the first byte. /// Should be less than the length of the collection of bytes to disassemble. /// </param> /// <param name="startingAddress"> /// The address of the first instruction in the collection of bytes to disassemble. /// </param> public DeferredInstructionEnumerable(CapstoneDisassembler <TArchitectureInstruction, TArchitectureRegister, TArchitectureGroup, TArchitectureDetail> disassembler, byte[] code, int offset, long startingAddress) { this._disassembler = disassembler; this._code = code; this._offset = offset; this._startingAddress = startingAddress; }
/// <summary> /// Created a Deferred Instruction Enumerator. /// </summary> /// <param name="disassembler"> /// The disassembler to use. Should not be a null reference. /// </param> /// <param name="code"> /// A collection of bytes representing the binary code to disassemble. Should not be a null reference. /// </param> /// <param name="offset"> /// An offset to start disassembling from. A 0 indicates disassembly should start at the first byte. /// Should be less than the length of the collection of bytes to disassemble. /// </param> /// <param name="startingAddress"> /// The address of the first instruction in the collection of bytes to disassemble. /// </param> public DeferredInstructionEnumerator(CapstoneDisassembler <TArchitectureInstruction, TArchitectureRegister, TArchitectureGroup, TArchitectureDetail> disassembler, byte[] code, int offset, long startingAddress) { this._disassembler = disassembler; this._pinnedCode = GCHandle.Alloc(code, GCHandleType.Pinned); this._currentOffset = offset; this._currentAddress = (ulong)startingAddress; this._codeSize = code.Length; this._disposed = false; }
/// <summary> /// Build an Instruction. /// </summary> /// <param name="disassembler"> /// A disassembler. /// </param> /// <param name="hInstruction"> /// An instruction handle. /// </param> internal virtual void Build(CapstoneDisassembler disassembler, NativeInstructionHandle hInstruction) { // ... // // Throws an exception if the operation fails. var nativeInstruction = NativeCapstone.GetInstruction(hInstruction); this.Address = nativeInstruction.Address; this.DisassembleArchitecture = disassembler.DisassembleArchitecture; this.DisassembleMode = this.CreateDisassembleMode(disassembler.NativeDisassembleMode); this.Id = this.CreateId(nativeInstruction.Id); this.IsSkippedData = disassembler.EnableSkipDataMode && !(nativeInstruction.Id > 0); this.Mnemonic = !CapstoneDisassembler.IsDietModeEnabled ? nativeInstruction.Mnemonic : null; this.Operand = !CapstoneDisassembler.IsDietModeEnabled ? nativeInstruction.Operand : null; // ... // // ... SetBytes(this, ref nativeInstruction); SetDetails(this, disassembler, hInstruction, ref nativeInstruction); // <summary> // Set Instruction's Machine Bytes. // </summary> void SetBytes(InstructionBuilder <TDetail, TDisassembleMode, TGroup, TGroupId, TInstruction, TId, TRegister, TRegisterId> @this, ref NativeInstruction cNativeInstruction) { @this.Bytes = new byte[0]; if (cNativeInstruction.Id >= 0) { @this.Bytes = new byte[cNativeInstruction.Size]; for (var cI = 0; cI < @this.Bytes.Length; cI++) { @this.Bytes[cI] = cNativeInstruction.Bytes[cI]; } } } // <summary> // Set Instruction's Details. // </summary> void SetDetails(InstructionBuilder <TDetail, TDisassembleMode, TGroup, TGroupId, TInstruction, TId, TRegister, TRegisterId> @this, CapstoneDisassembler cDisassembler, NativeInstructionHandle cHInstruction, ref NativeInstruction cNativeInstruction) { var cHasDetails = cNativeInstruction.Details != IntPtr.Zero; var cIsInstructionDetailsEnabled = cDisassembler.EnableInstructionDetails; @this.Details = null; if (cHasDetails && cIsInstructionDetailsEnabled && cNativeInstruction.Id > 0) { @this.Details = @this.CreateDetails(cDisassembler, cHInstruction); } } }
/// <summary> /// Create Instruction's Details. /// </summary> /// <param name="disassembler"> /// A disassembler. /// </param> /// <param name="hInstruction"> /// An instruction handle. /// </param> /// <returns> /// The instruction's details. /// </returns> private protected abstract TDetail CreateDetails(CapstoneDisassembler disassembler, NativeInstructionHandle hInstruction);
/// <summary> /// Build an Instruction Detail. /// </summary> /// <param name="disassembler"> /// A disassembler. /// </param> /// <param name="hInstruction"> /// An instruction handle. /// </param> internal virtual void Build(CapstoneDisassembler disassembler, NativeInstructionHandle hInstruction) { // ... // // Throws an exception if the operation fails. var nativeInstructionDetail = NativeCapstone.GetInstructionDetail(hInstruction).GetValueOrDefault(); this.DisassembleArchitecture = disassembler.DisassembleArchitecture; this.DisassembleMode = this.CreateDisassembleMode(disassembler.NativeDisassembleMode); // ... // // ... SetAccessedRegisters(this, disassembler, hInstruction); SetGroups(this, disassembler, ref nativeInstructionDetail); SetImplicitlyReadRegisters(this, disassembler, ref nativeInstructionDetail); SetImplicitlyWrittenRegisters(this, disassembler, ref nativeInstructionDetail); // <summary> // Set Accessed Registers. // </summary> void SetAccessedRegisters(InstructionDetailBuilder <TDetail, TDisassembleMode, TGroup, TGroupId, TInstruction, TInstructionId, TRegister, TRegisterId> @this, CapstoneDisassembler cDisassembler, NativeInstructionHandle cHInstruction) { @this.AllReadRegisters = new TRegister[0]; @this.AllWrittenRegisters = new TRegister[0]; if (!CapstoneDisassembler.IsDietModeEnabled) { var isArchSupported = cDisassembler.DisassembleArchitecture != DisassembleArchitecture.M68K; isArchSupported = isArchSupported && cDisassembler.DisassembleArchitecture != DisassembleArchitecture.Mips; isArchSupported = isArchSupported && cDisassembler.DisassembleArchitecture != DisassembleArchitecture.PowerPc; isArchSupported = isArchSupported && cDisassembler.DisassembleArchitecture != DisassembleArchitecture.XCore; if (isArchSupported) { // ... // // Throws an exception if the operation fails. var cAccessedRegisters = NativeCapstone.GetAccessedRegisters(cDisassembler.Handle, cHInstruction); @this.AllReadRegisters = new TRegister[cAccessedRegisters.Item1.Length]; for (var cI = 0; cI < @this.AllReadRegisters.Length; cI++) { var cExplicitlyReadRegister = cAccessedRegisters.Item1[cI]; @this.AllReadRegisters[cI] = @this.CreateRegister(cDisassembler, cExplicitlyReadRegister); } @this.AllWrittenRegisters = new TRegister[cAccessedRegisters.Item2.Length]; for (var cI = 0; cI < @this.AllWrittenRegisters.Length; cI++) { var cExplicitlyWrittenRegister = cAccessedRegisters.Item2[cI]; @this.AllWrittenRegisters[cI] = @this.CreateRegister(cDisassembler, cExplicitlyWrittenRegister); } } } } // <summary> // Set Instruction's Groups. // </summary> void SetGroups(InstructionDetailBuilder <TDetail, TDisassembleMode, TGroup, TGroupId, TInstruction, TInstructionId, TRegister, TRegisterId> @this, CapstoneDisassembler cDisassembler, ref NativeInstructionDetail cNativeInstructionDetail) { @this.Groups = new TGroup[cNativeInstructionDetail.GroupCount]; if (!CapstoneDisassembler.IsDietModeEnabled) { for (var cI = 0; cI < @this.Groups.Length; cI++) { var cGroup = cNativeInstructionDetail.Groups[cI]; @this.Groups[cI] = @this.CreateInstructionGroup(cDisassembler, cGroup); } } } // <summary> // Set Implicitly Read Registers. // </summary> void SetImplicitlyReadRegisters(InstructionDetailBuilder <TDetail, TDisassembleMode, TGroup, TGroupId, TInstruction, TInstructionId, TRegister, TRegisterId> @this, CapstoneDisassembler cDisassembler, ref NativeInstructionDetail cNativeInstructionDetail) { @this.ImplicitlyReadRegisters = new TRegister[cNativeInstructionDetail.ImplicitlyReadRegisterCount]; if (!CapstoneDisassembler.IsDietModeEnabled) { for (var cI = 0; cI < @this.ImplicitlyReadRegisters.Length; cI++) { var cImplicitlyReadRegister = cNativeInstructionDetail.ImplicitlyReadRegisters[cI]; @this.ImplicitlyReadRegisters[cI] = @this.CreateRegister(cDisassembler, cImplicitlyReadRegister); } } } // <summary> // Set Implicitly Written Registers. // </summary> void SetImplicitlyWrittenRegisters(InstructionDetailBuilder <TDetail, TDisassembleMode, TGroup, TGroupId, TInstruction, TInstructionId, TRegister, TRegisterId> @this, CapstoneDisassembler cDisassembler, ref NativeInstructionDetail cNativeInstructionDetail) { @this.ImplicitlyWrittenRegisters = new TRegister[cNativeInstructionDetail.ImplicitlyWrittenRegisterCount]; if (!CapstoneDisassembler.IsDietModeEnabled) { for (var cI = 0; cI < @this.ImplicitlyWrittenRegisters.Length; cI++) { var cImplicitlyWrittenRegister = cNativeInstructionDetail.ImplicitlyWrittenRegisters[cI]; @this.ImplicitlyWrittenRegisters[cI] = @this.CreateRegister(cDisassembler, cImplicitlyWrittenRegister); } } } }
/// <summary> /// Create a Register. /// </summary> /// <param name="disassembler"> /// A disassembler. /// </param> /// <param name="registerId"> /// A register's unique identifier. /// </param> /// <returns> /// A register. /// </returns> private protected abstract TRegister CreateRegister(CapstoneDisassembler disassembler, short registerId);
/// <summary> /// Create an Instruction Group. /// </summary> /// <param name="disassembler"> /// A disassembler. /// </param> /// <param name="instructionGroupId"> /// An instruction group's unique identifier. /// </param> /// <returns> /// An instruction group. /// </returns> private protected abstract TGroup CreateInstructionGroup(CapstoneDisassembler disassembler, byte instructionGroupId);