mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-11 09:36:10 +02:00
* finished disassembler
git-svn-id: trunk@9238 -
This commit is contained in:
parent
d14455fdbc
commit
6aae9024cc
@ -36,7 +36,7 @@ unit FPWDGlobal;
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Windows, FPWDType, Maps, WinDebugger;
|
||||
SysUtils, Windows, FPWDType, Maps, WinDebugger, WinDExtra;
|
||||
|
||||
type
|
||||
TMWDState = (dsStop, dsRun, dsPause, dsQuit, dsEvent);
|
||||
@ -60,6 +60,7 @@ var
|
||||
|
||||
|
||||
function GetProcess(const AID: Integer; var AProcess: TDbgProcess): Boolean;
|
||||
function FormatAddress(const AAddress): String;
|
||||
|
||||
implementation
|
||||
|
||||
@ -70,6 +71,13 @@ begin
|
||||
// then Log('Unknown Process ID %u', [AID]);
|
||||
end;
|
||||
|
||||
function FormatAddress(const AAddress): String;
|
||||
const
|
||||
SIZE: array[TMWDMode] of Integer = (4, 8);
|
||||
begin
|
||||
Result := HexValue(AAddress, SIZE[GMode], [hvfIncludeHexchar]);
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
_UnAligendContext: record
|
||||
|
@ -263,7 +263,7 @@ end;
|
||||
|
||||
function TDbgProcess.AddLib(const AInfo: TLoadDLLDebugInfo): TDbgLibrary;
|
||||
begin
|
||||
Result := TDbgLibrary.Create(Self, FormatAddress(AInfo.lpBaseOfDll), AInfo);
|
||||
Result := TDbgLibrary.Create(Self, HexValue(AInfo.lpBaseOfDll, SizeOf(Pointer), [hvfIncludeHexchar]), AInfo);
|
||||
FLibMap.Add(TDbgPtr(AInfo.lpBaseOfDll), Result);
|
||||
end;
|
||||
|
||||
@ -660,7 +660,7 @@ begin
|
||||
Context^.ContextFlags := CONTEXT_CONTROL;
|
||||
if not GetThreadContext(Thread.Handle, Context^)
|
||||
then begin
|
||||
Log('Break $s: Unable to get context', [FormatAddress(FLocation)]);
|
||||
Log('Break $s: Unable to get context', [HexValue(FLocation, SizeOf(Pointer), [hvfIncludeHexchar])]);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
@ -673,7 +673,7 @@ begin
|
||||
|
||||
if not SetThreadContext(Thread.Handle, Context^)
|
||||
then begin
|
||||
Log('Break %s: Unable to set context', [FormatAddress(FLocation)]);
|
||||
Log('Break %s: Unable to set context', [HexValue(FLocation, SizeOf(Pointer), [hvfIncludeHexchar])]);
|
||||
Exit;
|
||||
end;
|
||||
Result := True;
|
||||
|
@ -43,11 +43,16 @@ uses
|
||||
type
|
||||
TDbgPtr = PtrUInt;
|
||||
|
||||
type
|
||||
THexValueFormatFlag = (hvfSigned, hvfPrefixPositive, hvfIncludeHexchar);
|
||||
THexValueFormatFlags = set of THexValueFormatFlag;
|
||||
|
||||
|
||||
function GetLastErrorText(AErrorCode: Cardinal): String; {$IFNDEF FPC} overload; {$ENDIF}
|
||||
function GetLastErrorText: String; {$IFNDEF FPC} overload; {$ENDIF}
|
||||
|
||||
function FormatAddress(const P): String;
|
||||
function AlignPtr(Src: Pointer; Alignment: Byte): Pointer;
|
||||
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
||||
procedure Log(const AText: String; const AParams: array of const); overload;
|
||||
procedure Log(const AText: String); overload;
|
||||
|
||||
@ -59,23 +64,53 @@ procedure Log(const AText: String); overload;
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils, FPWDGLobal;
|
||||
SysUtils;
|
||||
|
||||
//function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall; external 'kernel32';
|
||||
//function Wow64GetThreadContext(hThread: THandle; var lpContext: TContext): BOOL; stdcall; external 'kernel32';
|
||||
|
||||
|
||||
function FormatAddress(const P): String;
|
||||
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
||||
var
|
||||
i: Int64;
|
||||
p: PByte;
|
||||
begin
|
||||
case GMode of
|
||||
dm32: Result := '$' + IntToHex(DWord(p), 8);
|
||||
dm64: Result := '$' + IntToHex(int64(p), 16);
|
||||
else
|
||||
Result := 'Unknown mode';
|
||||
if ASize > 8
|
||||
then begin
|
||||
Result := 'HexValue: size to large';
|
||||
Exit;
|
||||
end;
|
||||
if ASize = 0
|
||||
then begin
|
||||
Result := '';
|
||||
Exit;
|
||||
end;
|
||||
|
||||
p := @AValue;
|
||||
if p[ASize - 1] < $80
|
||||
then Exclude(AFlags, hvfSigned);
|
||||
|
||||
if hvfSigned in AFlags
|
||||
then i := -1
|
||||
else i := 0;
|
||||
|
||||
Move(AValue, i, ASize);
|
||||
if hvfSigned in AFlags
|
||||
then begin
|
||||
i := not i + 1;
|
||||
Result := '-';
|
||||
end
|
||||
else begin
|
||||
if hvfPrefixPositive in AFlags
|
||||
then Result := '+';
|
||||
end;
|
||||
if hvfIncludeHexchar in AFlags
|
||||
then Result := Result + '$';
|
||||
|
||||
Result := Result + HexStr(i, ASize * 2);
|
||||
end;
|
||||
|
||||
|
||||
function GetLastErrorText: String;
|
||||
begin
|
||||
Result := GetLastErrorText(GetLastError);
|
||||
|
@ -36,6 +36,7 @@ unit WinDisas;
|
||||
interface
|
||||
|
||||
{.$define debug_OperandSize}
|
||||
{.$define verbose_string_instructions}
|
||||
|
||||
uses
|
||||
SysUtils, Windows, WindExtra;
|
||||
@ -53,8 +54,9 @@ uses
|
||||
}
|
||||
|
||||
|
||||
procedure Disassemble(const AProcess: Handle; const A64Bit: Boolean; var Address: TDbgPtr; out ACodeBytes: String; out ACode: String);
|
||||
function Disassemble(const AProcess: Handle; const A64Bit: Boolean; var Address: TDbgPtr): String;
|
||||
procedure Disassemble(var AAddress: Pointer; const A64Bit: Boolean; out ACodeBytes: String; out ACode: String);
|
||||
procedure Disassemble(const AProcess: Handle; const A64Bit: Boolean; var AAddress: TDbgPtr; out ACodeBytes: String; out ACode: String);
|
||||
function Disassemble(const AProcess: Handle; const A64Bit: Boolean; var AAddress: TDbgPtr): String;
|
||||
|
||||
implementation
|
||||
|
||||
@ -62,76 +64,64 @@ type
|
||||
TFlag = (flagRex, flagSib, flagModRM, rexB, rexX, rexR, rexW, preOpr, preAdr, preLock, preRep{N}, preRepNE);
|
||||
TFlags = set of TFlag;
|
||||
|
||||
TOperandSize = (os8, os16, os32, os64, os80);
|
||||
// Keep 8,16,32,64 together
|
||||
TOperandSize = (os8, os16, os32, os64, os48, os80, os128);
|
||||
TAddressSize = (as16, as32, as64);
|
||||
TRegisterType = (reg8, reg16, reg32, reg64, regMmx, regXmm, regSegment, regControl, regDebug);
|
||||
TRegisterType = (reg0, reg8, reg16, reg32, reg64, regMmx, regXmm, regSegment, regControl, regDebug, regX87);
|
||||
TModRMType = (modReg, modMem);
|
||||
TModRMTypes = set of TModRMType;
|
||||
|
||||
|
||||
const
|
||||
ADDRESS_BYTES: array[TAddressSize] of Byte = (2, 4, 8);
|
||||
OPERAND_BYTES: array[TOperandSize] of Byte = (1, 2, 4, 8, 10);
|
||||
OPERAND_BYTES: array[TOperandSize] of Byte = (1, 2, 4, 8, 6, 10, 16);
|
||||
OPERAND_REG: array[os8..os64] of TRegisterType = (reg8, reg16, reg32, reg64);
|
||||
STD_REGS = [reg8..reg64];
|
||||
|
||||
type
|
||||
THexValueFormatFlag = (hvfSigned, hvfPrefixPositive, hvfIncludeHexchar);
|
||||
THexValueFormatFlags = set of THexValueFormatFlag;
|
||||
TOperandFlag = (ofMemory);
|
||||
TOperandFlags = set of TOperandFlag;
|
||||
|
||||
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
||||
var
|
||||
i: Int64;
|
||||
p: PByte;
|
||||
begin
|
||||
if ASize > 8
|
||||
then begin
|
||||
Result := 'HexValue: size to large';
|
||||
Exit;
|
||||
end;
|
||||
if ASize = 0
|
||||
then begin
|
||||
Result := '';
|
||||
Exit;
|
||||
end;
|
||||
|
||||
p := @AValue;
|
||||
if p[ASize - 1] < $80
|
||||
then Exclude(AFlags, hvfSigned);
|
||||
|
||||
if hvfSigned in AFlags
|
||||
then i := -1
|
||||
else i := 0;
|
||||
|
||||
Move(AValue, i, ASize);
|
||||
if hvfSigned in AFlags
|
||||
then begin
|
||||
i := not i + 1;
|
||||
Result := '-';
|
||||
end
|
||||
else begin
|
||||
if hvfPrefixPositive in AFlags
|
||||
then Result := '+';
|
||||
end;
|
||||
if hvfIncludeHexchar in AFlags
|
||||
then Result := Result + '$';
|
||||
|
||||
Result := Result + HexStr(i, ASize * 2);
|
||||
end;
|
||||
|
||||
function Disassemble(const AProcess: Handle; const A64Bit: Boolean; var Address: TDbgPtr): String;
|
||||
function Disassemble(const AProcess: Handle; const A64Bit: Boolean; var AAddress: TDbgPtr): String;
|
||||
var
|
||||
S: String;
|
||||
begin
|
||||
Disassemble(AProcess, A64bit, Address, S, Result);
|
||||
Disassemble(AProcess, A64bit, AAddress, S, Result);
|
||||
end;
|
||||
|
||||
procedure Disassemble(const AProcess: Handle; const A64Bit: Boolean; var Address: TDbgPtr; out ACodeBytes: String; out ACode: String);
|
||||
procedure Disassemble(const AProcess: Handle; const A64Bit: Boolean; var AAddress: TDbgPtr; out ACodeBytes: String; out ACode: String);
|
||||
const
|
||||
PTRSIZE: array[Boolean] of Byte = (4, 8);
|
||||
var
|
||||
BytesRead: Cardinal;
|
||||
Code: array[0..20] of Byte;
|
||||
p: Pointer;
|
||||
begin
|
||||
BytesRead := 0;
|
||||
if not ReadProcessMemory(AProcess, Pointer(AAddress), @Code, SizeOf(Code), BytesRead) and (BytesRead = SizeOf(Code))
|
||||
then begin
|
||||
Log('Disassemble: Failed to read memory at %s, got %u bytes', [HexValue(AAddress, PTRSIZE[A64Bit], [hvfIncludeHexchar]), BytesRead]);
|
||||
ACode := '??';
|
||||
ACodeBytes := '??';
|
||||
Inc(AAddress);
|
||||
Exit;
|
||||
end;
|
||||
p := @Code;
|
||||
Disassemble(p, A64Bit, ACodeBytes, ACode);
|
||||
Inc(AAddress, PtrUInt(p) - PtrUInt(@Code));
|
||||
end;
|
||||
|
||||
procedure Disassemble(var AAddress: Pointer; const A64Bit: Boolean; out ACodeBytes: String; out ACode: String);
|
||||
var
|
||||
Code: PByte;
|
||||
CodeIdx: Byte;
|
||||
Operand: array[1..4] of record
|
||||
Value: String;
|
||||
Size: TOperandSize;
|
||||
ByteCount: Byte;
|
||||
ByteCount2: Byte;
|
||||
FormatFlags: THexValueFormatFlags;
|
||||
IsMemory: Boolean;
|
||||
Flags: TOperandFlags;
|
||||
end;
|
||||
OperIdx: Byte;
|
||||
ModRMIdx: Byte;
|
||||
@ -170,14 +160,14 @@ var
|
||||
begin
|
||||
Result := True;
|
||||
for n := 1 to OperIdx do
|
||||
if Operand[n].IsMemory then Exit;
|
||||
if ofMemory in Operand[n].Flags then Exit;
|
||||
Result := False;
|
||||
end;
|
||||
begin
|
||||
if (preLock in Flags) and CheckMem
|
||||
then begin
|
||||
Exclude(Flags, preLock);
|
||||
Result := 'lock: ' + AOpcode;
|
||||
Result := 'lock ' + AOpcode;
|
||||
Exit;
|
||||
end;
|
||||
Result := AOpcode;
|
||||
@ -188,7 +178,7 @@ var
|
||||
if preRep in Flags
|
||||
then begin
|
||||
Exclude(Flags, preRep);
|
||||
Result := 'rep: ' + AOpcode;
|
||||
Result := 'rep ' + AOpcode;
|
||||
Exit;
|
||||
end;
|
||||
Result := AOpcode;
|
||||
@ -199,13 +189,13 @@ var
|
||||
if preRep in Flags
|
||||
then begin
|
||||
Exclude(Flags, preRep);
|
||||
Result := 'repe: ' + AOpcode;
|
||||
Result := 'repe ' + AOpcode;
|
||||
Exit;
|
||||
end;
|
||||
if preRepNE in Flags
|
||||
then begin
|
||||
Exclude(Flags, preRepNE);
|
||||
Result := 'repe: ' + AOpcode;
|
||||
Result := 'repne ' + AOpcode;
|
||||
Exit;
|
||||
end;
|
||||
Result := AOpcode;
|
||||
@ -274,7 +264,7 @@ var
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure AddOperand(const AValue: String; ASize: TOperandSize; AByteCount: Byte = 0; AFormatFlags: THexValueFormatFlags = []; AIsMemory: Boolean = False);
|
||||
procedure AddOperand(const AValue: String; ASize: TOperandSize; AByteCount: Byte = 0; AFormatFlags: THexValueFormatFlags = []; AFlags: TOperandFlags = []; AByteCount2: Byte = 0);
|
||||
begin
|
||||
Inc(OperIdx);
|
||||
if OperIdx > High(Operand)
|
||||
@ -285,14 +275,15 @@ var
|
||||
|
||||
Operand[OperIdx].Size := ASize;
|
||||
Operand[OperIdx].ByteCount := AByteCount;
|
||||
Operand[OperIdx].ByteCount2 := AByteCount2;
|
||||
Operand[OperIdx].FormatFlags := AFormatFlags;
|
||||
Operand[OperIdx].Value := AValue;
|
||||
Operand[OperIdx].IsMemory := AIsMemory;
|
||||
Operand[OperIdx].Flags := AFlags;
|
||||
end;
|
||||
|
||||
procedure AddOperand(const AValue: String; AByteCount: Byte = 0; AFormatFlags: THexValueFormatFlags = []; AIsMemory: Boolean = False);
|
||||
procedure AddOperand(const AValue: String; AByteCount: Byte = 0; AFormatFlags: THexValueFormatFlags = []; AFlags: TOperandFlags = []);
|
||||
begin
|
||||
AddOperand(AValue, OperandSize32, AByteCount, AFormatFlags, AIsMemory);
|
||||
AddOperand(AValue, OperandSize32, AByteCount, AFormatFlags, AFlags);
|
||||
end;
|
||||
|
||||
function SizeReg32(const AReg: String; ASize: TOperandSize): String;
|
||||
@ -345,6 +336,9 @@ var
|
||||
then Result := Format('r%d', [8 + AIndex]) + POSTFIX[AType]
|
||||
else Result := SizeReg32(REGS[AIndex], OSMAP[AType]);
|
||||
end;
|
||||
regX87: begin
|
||||
Result := Format('st(%d)', [AIndex]);
|
||||
end;
|
||||
regMmx: begin
|
||||
Result := Format('mmx%d', [AIndex]);
|
||||
end;
|
||||
@ -370,22 +364,42 @@ var
|
||||
begin
|
||||
Result := StdReg(AIndex, OPERAND_REG[OperandSize32], rexR in Flags);
|
||||
end;
|
||||
|
||||
|
||||
procedure AddStdReg(AIndex: Byte; AType: TRegisterType; AExtReg: Boolean);
|
||||
const
|
||||
// reg8, reg16, reg32, reg64, regMmx, regXmm, regSegment, regControl, regDebug, regX87
|
||||
REGSIZE: array[Boolean, reg8..High(TRegisterType)] of TOperandSize = (
|
||||
{32}(os8, os16, os32, os64, os64, os128, os16, os32, os32, os80),
|
||||
{64}(os8, os16, os32, os64, os64, os128, os16, os64, os64, os80)
|
||||
);
|
||||
begin
|
||||
AddOperand(StdReg(AIndex, AType, AExtReg), REGSIZE[A64Bit, AType]);
|
||||
end;
|
||||
|
||||
procedure AddStdReg(AIndex: Byte);
|
||||
begin
|
||||
AddOperand(StdReg(AIndex, OPERAND_REG[OperandSize32], rexR in Flags));
|
||||
end;
|
||||
|
||||
procedure AddModReg(AType: TRegisterType; ASize: TOperandSize);
|
||||
begin
|
||||
Include(Flags, flagModRM);
|
||||
AddOperand(StdReg(Code[ModRMIdx] shr 3, AType, False), ASize);
|
||||
end;
|
||||
|
||||
procedure AddModReg(AType: TRegisterType; AExtReg: Boolean);
|
||||
begin
|
||||
Include(Flags, flagModRM);
|
||||
AddOperand(StdReg((Code[ModRMIdx] shr 3), AType, AExtReg));
|
||||
AddStdReg(Code[ModRMIdx] shr 3, AType, AExtReg);
|
||||
end;
|
||||
|
||||
procedure AddModReg;
|
||||
begin
|
||||
Include(Flags, flagModRM);
|
||||
AddOperand(StdReg((Code[ModRMIdx] shr 3), OPERAND_REG[OperandSize32], rexR in Flags));
|
||||
AddStdReg(Code[ModRMIdx] shr 3);
|
||||
end;
|
||||
|
||||
|
||||
procedure AddModRM(AAllowReg, AAllowMem: Boolean; ASize: TOperandSize);
|
||||
procedure AddModRM(AReqTypes: TModRMTypes; ASize: TOperandSize; AType: TRegisterType);
|
||||
var
|
||||
Mode, Rm: Byte;
|
||||
procedure Mem16;
|
||||
@ -395,11 +409,11 @@ var
|
||||
case Mode of
|
||||
0: begin
|
||||
if rm = 6 // disp16 -> exeption to the regs
|
||||
then AddOperand('%s', ASize, 2, [hvfSigned, hvfIncludeHexchar], True)
|
||||
else AddOperand(REGS16[rm], ASize, 0, [], True);
|
||||
then AddOperand('%s', ASize, 2, [hvfSigned, hvfIncludeHexchar], [ofMemory])
|
||||
else AddOperand(REGS16[rm], ASize, 0, [], [ofMemory]);
|
||||
end;
|
||||
1: AddOperand(REGS16[rm] + '%s', ASize, 1, [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar], True);
|
||||
2: AddOperand(REGS16[rm] + '%s', ASize, 2, [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar], True);
|
||||
1: AddOperand(REGS16[rm] + '%s', ASize, 1, [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar], [ofMemory]);
|
||||
2: AddOperand(REGS16[rm] + '%s', ASize, 2, [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar], [ofMemory]);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -421,16 +435,16 @@ var
|
||||
// Check for reg (mode = 3) first;
|
||||
if mode = 3
|
||||
then begin
|
||||
if not AAllowReg
|
||||
then AddOperand('**')
|
||||
else AddOperand(StdReg(rm, OPERAND_REG[ASize], False), ASize);
|
||||
if modReg in AReqTypes
|
||||
then AddStdReg(rm, AType, False)
|
||||
else AddOperand('**');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// Check if mem is allowed
|
||||
if not AAllowMem
|
||||
if not (modMem in AReqTypes)
|
||||
then begin
|
||||
AddOperand('**', 0, [], True);
|
||||
AddOperand('**', 0, [], [ofMemory]);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
@ -520,13 +534,15 @@ var
|
||||
Oper.Flags := [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar];
|
||||
end;
|
||||
end;
|
||||
AddOperand(Oper.Value, ASize, Oper.Size, Oper.Flags, True);
|
||||
AddOperand(Oper.Value, ASize, Oper.Size, Oper.Flags, [ofMemory]);
|
||||
end;
|
||||
//===================
|
||||
|
||||
procedure AddAp;
|
||||
begin
|
||||
AddOperand('Ap');
|
||||
if OperandSize32 = os16 //XXXX:XXXX
|
||||
then AddOperand('$%1:s:%0:s', os32, 2, [], [], 2)
|
||||
else AddOperand('$%1:s:%0:s', os48, 4, [], [], 2)
|
||||
end;
|
||||
|
||||
procedure AddCd_q;
|
||||
@ -541,29 +557,29 @@ var
|
||||
|
||||
procedure AddEb;
|
||||
begin
|
||||
AddModRM(True, True, os8);
|
||||
AddModRM([modReg, modMem], os8, reg8);
|
||||
end;
|
||||
|
||||
procedure AddEd;
|
||||
begin
|
||||
AddModRM(True, True, os32);
|
||||
AddModRM([modReg, modMem], os32, reg32);
|
||||
end;
|
||||
|
||||
procedure AddEd_q;
|
||||
begin
|
||||
if flagRex in Flags
|
||||
then AddModRM(True, True, os64)
|
||||
else AddModRM(True, True, os32);
|
||||
then AddModRM([modReg, modMem], os64, reg64)
|
||||
else AddModRM([modReg, modMem], os32, reg32);
|
||||
end;
|
||||
|
||||
procedure AddEv;
|
||||
begin
|
||||
AddModRM(True, True, OperandSize32);
|
||||
AddModRM([modReg, modMem], OperandSize32, OPERAND_REG[OperandSize32]);
|
||||
end;
|
||||
|
||||
procedure AddEw;
|
||||
begin
|
||||
AddModRM(True, True, os16);
|
||||
AddModRM([modReg, modMem], os16, reg16);
|
||||
end;
|
||||
|
||||
procedure AddFv;
|
||||
@ -646,92 +662,104 @@ var
|
||||
|
||||
procedure AddM;
|
||||
begin
|
||||
AddModRM(False, True, OperandSize32);
|
||||
AddModRM([modMem], OperandSize32, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMa;
|
||||
begin
|
||||
AddOperand('Ma');
|
||||
AddModRM([modMem], OperandSize32, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMb;
|
||||
begin
|
||||
AddOperand('Ma');
|
||||
AddModRM([modMem], os8, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMd;
|
||||
begin
|
||||
AddOperand('Md');
|
||||
AddModRM([modMem], os32, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMd_q;
|
||||
begin
|
||||
AddOperand('Md/q');
|
||||
if flagRex in Flags
|
||||
then AddModRM([modMem], os64, reg0 {dont care})
|
||||
else AddModRM([modMem], os32, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMdq;
|
||||
begin
|
||||
AddOperand('Mdq');
|
||||
AddModRM([modMem], os128, reg0 {dont care})
|
||||
end;
|
||||
|
||||
procedure AddMp;
|
||||
begin
|
||||
AddOperand('Mp');
|
||||
if OperandSize32 = os16 //XXXX:XXXX
|
||||
then AddModRM([modMem], os32, reg0 {dont care})
|
||||
else AddModRM([modMem], os48, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMq;
|
||||
begin
|
||||
AddOperand('Mq');
|
||||
AddModRM([modMem], os64, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMs;
|
||||
begin
|
||||
AddOperand('Ms');
|
||||
if A64Bit
|
||||
then AddModRM([modMem], os80, reg0 {dont care})
|
||||
else AddModRM([modMem], os48, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMw_Rv;
|
||||
begin
|
||||
AddOperand('Mw/Rv');
|
||||
if Code[ModRMIdx] shr 6 = 3 // mode = 3 -> reg
|
||||
then AddModRM([modReg], OperandSize32, OPERAND_REG[OperandSize32])
|
||||
else AddModRM([modMem], os16, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddOb;
|
||||
begin
|
||||
AddOperand('%s', os8, ADDRESS_BYTES[AddressSize32], [hvfIncludeHexchar], True)
|
||||
AddOperand('%s', os8, ADDRESS_BYTES[AddressSize32], [hvfIncludeHexchar], [ofMemory])
|
||||
end;
|
||||
|
||||
procedure AddOv;
|
||||
begin
|
||||
AddOperand('%s', ADDRESS_BYTES[AddressSize32], [hvfIncludeHexchar], True)
|
||||
AddOperand('%s', ADDRESS_BYTES[AddressSize32], [hvfIncludeHexchar], [ofMemory])
|
||||
end;
|
||||
|
||||
procedure AddPd_q;
|
||||
begin
|
||||
AddOperand('Pd/q');
|
||||
if flagRex in Flags
|
||||
then AddModReg(regMmx, os64)
|
||||
else AddModReg(regMmx, os32);
|
||||
end;
|
||||
|
||||
procedure AddPq;
|
||||
begin
|
||||
AddOperand('Pq');
|
||||
AddModReg(regMmx, False);
|
||||
end;
|
||||
|
||||
procedure AddPRq;
|
||||
begin
|
||||
AddOperand('PRq');
|
||||
AddModRM([modReg], os64, regMmx);
|
||||
end;
|
||||
|
||||
procedure AddQd;
|
||||
begin
|
||||
AddOperand('Qd');
|
||||
AddModRM([modReg, modMem], os32, regMmx);
|
||||
end;
|
||||
|
||||
procedure AddQq;
|
||||
begin
|
||||
AddOperand('Qq');
|
||||
AddModRM([modReg, modMem], os64, regMmx);
|
||||
end;
|
||||
|
||||
procedure AddRd_q;
|
||||
begin
|
||||
AddModRM(True, False, OperandSize32);
|
||||
if A64Bit
|
||||
then AddModRM([modReg], os64, reg64)
|
||||
else AddModRM([modReg], os32, reg32);
|
||||
end;
|
||||
|
||||
procedure AddSw;
|
||||
@ -741,99 +769,102 @@ var
|
||||
|
||||
procedure AddVd_q;
|
||||
begin
|
||||
AddOperand('Vd/q');
|
||||
if flagRex in Flags
|
||||
then AddModReg(regXmm, os64)
|
||||
else AddModReg(regXmm, os32);
|
||||
end;
|
||||
|
||||
procedure AddVdq;
|
||||
begin
|
||||
AddOperand('Vdq');
|
||||
AddModReg(regXmm, os128);
|
||||
end;
|
||||
|
||||
procedure AddVdq_sd;
|
||||
begin
|
||||
AddOperand('Vdq/sd');
|
||||
AddModReg(regXmm, os64); // only lower 64 bit
|
||||
end;
|
||||
|
||||
procedure AddVdq_ss;
|
||||
begin
|
||||
AddOperand('Vdq/ss');
|
||||
AddModReg(regXmm, os32); // only lower 32 bit
|
||||
end;
|
||||
|
||||
procedure AddVpd;
|
||||
begin
|
||||
AddOperand('Vsd');
|
||||
AddModReg(regXmm, os128);
|
||||
end;
|
||||
|
||||
procedure AddVps;
|
||||
begin
|
||||
AddOperand('Vps');
|
||||
AddModReg(regXmm, os128);
|
||||
end;
|
||||
|
||||
procedure AddVq;
|
||||
begin
|
||||
AddOperand('Vq');
|
||||
AddModReg(regXmm, os64);
|
||||
end;
|
||||
|
||||
procedure AddVsd;
|
||||
begin
|
||||
AddOperand('Vsd');
|
||||
AddModReg(regXmm, os64);
|
||||
end;
|
||||
|
||||
procedure AddVss;
|
||||
begin
|
||||
AddOperand('Vss');
|
||||
AddModReg(regXmm, os32);
|
||||
end;
|
||||
|
||||
procedure AddVRdq;
|
||||
begin
|
||||
AddOperand('VRdq');
|
||||
AddModRM([modReg], os128, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddVRpd;
|
||||
begin
|
||||
AddOperand('VRpd');
|
||||
AddModRM([modReg], os128, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddVRps;
|
||||
begin
|
||||
AddOperand('VRps');
|
||||
AddModRM([modReg], os128, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddVRq;
|
||||
begin
|
||||
AddOperand('VRq');
|
||||
AddModRM([modReg], os64, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddWdq;
|
||||
begin
|
||||
AddOperand('Wdq');
|
||||
AddModRM([modReg, modMem], os128, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddWpd;
|
||||
begin
|
||||
AddOperand('Wpd');
|
||||
AddModRM([modReg, modMem], os128, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddWps;
|
||||
begin
|
||||
AddOperand('Wps');
|
||||
AddModRM([modReg, modMem], os128, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddWq;
|
||||
begin
|
||||
AddOperand('Wq');
|
||||
AddModRM([modReg, modMem], os64, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddWsd;
|
||||
begin
|
||||
AddOperand('Wsd');
|
||||
AddModRM([modReg, modMem], os64, regXmm);
|
||||
end;
|
||||
|
||||
procedure AddWss;
|
||||
begin
|
||||
AddOperand('Wss');
|
||||
AddModRM([modReg, modMem], os32, regXmm);
|
||||
end;
|
||||
|
||||
{$ifdef verbose_string_instructions}
|
||||
procedure AddXb;
|
||||
begin
|
||||
AddOperand('Xb');
|
||||
@ -863,7 +894,7 @@ var
|
||||
begin
|
||||
AddOperand('Yz');
|
||||
end;
|
||||
|
||||
{$endif}
|
||||
//===================
|
||||
|
||||
procedure AddStdOperands(AIndex: Byte);
|
||||
@ -892,32 +923,32 @@ var
|
||||
|
||||
procedure AddMem14_28Env;
|
||||
begin
|
||||
AddModRM(False, True, OperandSize32);
|
||||
AddModRM([modMem], OperandSize32, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMem98_108Env;
|
||||
begin
|
||||
AddModRM(False, True, OperandSize32);
|
||||
AddModRM([modMem], OperandSize32, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMem16;
|
||||
begin
|
||||
AddModRM(False, True, os16);
|
||||
AddModRM([modMem], os16, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMem32;
|
||||
begin
|
||||
AddModRM(False, True, os32);
|
||||
AddModRM([modMem], os32, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMem64;
|
||||
begin
|
||||
AddModRM(False, True, os64);
|
||||
AddModRM([modMem], os64, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddMem80;
|
||||
begin
|
||||
AddModRM(False, True, os80);
|
||||
AddModRM([modMem], os80, reg0 {dont care});
|
||||
end;
|
||||
|
||||
procedure AddReg(AIndex: Byte);
|
||||
@ -1128,6 +1159,7 @@ var
|
||||
for n := 1 to OperIdx do
|
||||
begin
|
||||
Inc(idx, Operand[n].ByteCount);
|
||||
Inc(idx, Operand[n].ByteCount2);
|
||||
end;
|
||||
// now we can lookup the opcode
|
||||
case Code[CodeIdx + idx] of
|
||||
@ -1701,7 +1733,7 @@ var
|
||||
// it is specified as Mq or VRq
|
||||
// So when getting Wq, we Add both and know the type
|
||||
AddVps; AddWq;
|
||||
if Operand[2].IsMemory
|
||||
if ofMemory in Operand[2].Flags
|
||||
then Opcode := 'movlps';
|
||||
end;
|
||||
1: begin AddVps; AddWps; end;
|
||||
@ -1738,7 +1770,7 @@ var
|
||||
// it is specified as Mq or VRq
|
||||
// So when getting Wq, we Add both and know the type
|
||||
AddVps; AddWq;
|
||||
if Operand[2].IsMemory
|
||||
if ofMemory in Operand[2].Flags
|
||||
then Opcode := 'movhps';
|
||||
end;
|
||||
1: begin AddVps; AddWps; end;
|
||||
@ -2271,7 +2303,7 @@ var
|
||||
end;
|
||||
$C8..$CF: begin
|
||||
Opcode := 'bswp';
|
||||
AddOperand(StdReg(Code[CodeIdx]));
|
||||
AddStdReg(Code[CodeIdx]);
|
||||
end;
|
||||
//---
|
||||
$D0: begin
|
||||
@ -2481,7 +2513,7 @@ var
|
||||
Include(Flags, flagRex);
|
||||
end
|
||||
else begin
|
||||
AddOperand(StdReg(Code[CodeIdx]));
|
||||
AddStdReg(Code[CodeIdx]);
|
||||
if Code[CodeIdx] <= $47
|
||||
then Opcode := CheckLock('inc')
|
||||
else Opcode := CheckLock('dec');
|
||||
@ -2490,11 +2522,11 @@ var
|
||||
//---
|
||||
$50..$57: begin
|
||||
Opcode := 'push';
|
||||
AddOperand(StdReg(Code[CodeIdx]));
|
||||
AddStdReg(Code[CodeIdx]);
|
||||
end;
|
||||
$58..$5F: begin
|
||||
Opcode := 'pop';
|
||||
AddOperand(StdReg(Code[CodeIdx]));
|
||||
AddStdReg(Code[CodeIdx]);
|
||||
end;
|
||||
//---
|
||||
$60: begin
|
||||
@ -2552,27 +2584,35 @@ var
|
||||
end;
|
||||
$6C: begin
|
||||
Opcode := CheckRepeat('insb');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddYb;
|
||||
AddOperand('dx', os16);
|
||||
{$endif}
|
||||
end;
|
||||
$6D: begin
|
||||
if OperandSize32 = os16
|
||||
then Opcode := CheckRepeat('insw')
|
||||
else Opcode := CheckRepeat('insd');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddYz;
|
||||
AddOperand('dx', os16);
|
||||
{$endif}
|
||||
end;
|
||||
$6E: begin
|
||||
Opcode := CheckRepeat('outsb');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddOperand('dx', os16);
|
||||
AddXb;
|
||||
{$endif}
|
||||
end;
|
||||
$6F: begin
|
||||
if OperandSize32 = os16
|
||||
then Opcode := CheckRepeat('outsw')
|
||||
else Opcode := CheckRepeat('outsd');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddOperand('dx', os16);
|
||||
AddXz;
|
||||
{$endif}
|
||||
end;
|
||||
$70..$7F: begin
|
||||
Opcode := 'j' + StdCond(Code[CodeIdx]);
|
||||
@ -2623,7 +2663,7 @@ var
|
||||
then Opcode := 'nop'
|
||||
else begin
|
||||
Opcode := 'xchg';
|
||||
AddOperand(StdReg(Code[CodeIdx]));
|
||||
AddStdReg(Code[CodeIdx]);
|
||||
AddOperand(SizeReg32('ax'));
|
||||
end;
|
||||
end;
|
||||
@ -2697,7 +2737,9 @@ var
|
||||
end;
|
||||
$A4: begin
|
||||
Opcode := CheckRepeat('movsb');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddYb; AddXb;
|
||||
{$endif}
|
||||
end;
|
||||
$A5: begin
|
||||
case OperandSize32 of
|
||||
@ -2706,12 +2748,15 @@ var
|
||||
else
|
||||
Opcode := CheckRepeat('movsw');
|
||||
end;
|
||||
AddYv;
|
||||
AddXv;
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddYv; AddXv;
|
||||
{$endif}
|
||||
end;
|
||||
$A6: begin
|
||||
Opcode := CheckRepeatX('cmpsb');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddXb; AddYb;
|
||||
{$endif}
|
||||
end;
|
||||
$A7: begin
|
||||
case OperandSize32 of
|
||||
@ -2720,7 +2765,9 @@ var
|
||||
else
|
||||
Opcode := CheckRepeatX('cmpsw');
|
||||
end;
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddYv; AddXv;
|
||||
{$endif}
|
||||
end;
|
||||
$A8: begin
|
||||
Opcode := 'test';
|
||||
@ -2734,8 +2781,10 @@ var
|
||||
end;
|
||||
$AA: begin
|
||||
Opcode := CheckRepeat('stosb');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddYb;
|
||||
AddOperand('al', os8);
|
||||
{$endif}
|
||||
end;
|
||||
$AB: begin
|
||||
case OperandSize32 of
|
||||
@ -2744,13 +2793,17 @@ var
|
||||
else
|
||||
Opcode := CheckRepeat('stosw');
|
||||
end;
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddYv;
|
||||
AddOperand(SizeReg32('ax'));
|
||||
{$endif}
|
||||
end;
|
||||
$AC: begin
|
||||
Opcode := CheckRepeat('lodsb');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddOperand('al', os8);
|
||||
AddXb;
|
||||
{$endif}
|
||||
end;
|
||||
$AD: begin
|
||||
case OperandSize32 of
|
||||
@ -2759,13 +2812,17 @@ var
|
||||
else
|
||||
Opcode := CheckRepeat('lodsw');
|
||||
end;
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddOperand(SizeReg32('ax'));
|
||||
AddXv;
|
||||
{$endif}
|
||||
end;
|
||||
$AE: begin
|
||||
Opcode := CheckRepeatX('scasb');
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddOperand('al', os8);
|
||||
AddYb;
|
||||
{$endif}
|
||||
end;
|
||||
$AF: begin
|
||||
case OperandSize32 of
|
||||
@ -2774,18 +2831,20 @@ var
|
||||
else
|
||||
Opcode := CheckRepeatX('scasw');
|
||||
end;
|
||||
{$ifdef verbose_string_instructions}
|
||||
AddOperand(SizeReg32('ax'));
|
||||
AddYv;
|
||||
{$endif}
|
||||
end;
|
||||
//---
|
||||
$B0..$B7: begin
|
||||
Opcode := 'mov';
|
||||
AddOperand(StdReg(Code[CodeIdx], reg8, rexR in Flags), os8);
|
||||
AddStdReg(Code[CodeIdx], reg8, rexR in Flags);
|
||||
AddIb;
|
||||
end;
|
||||
$B8..$BF: begin
|
||||
Opcode := 'mov';
|
||||
AddOperand(StdReg(Code[CodeIdx]));
|
||||
AddStdReg(Code[CodeIdx]);
|
||||
AddIv;
|
||||
end;
|
||||
//---
|
||||
@ -2984,33 +3043,25 @@ var
|
||||
end;
|
||||
|
||||
Inc(CodeIdx);
|
||||
if CodeIdx > High(Code)
|
||||
if CodeIdx > 16 // max instruction length
|
||||
then begin
|
||||
Log('Disassemble: instruction longer than %d bytes', [SizeOf(Code)]);
|
||||
Log('Disassemble: instruction longer than 16 bytes');
|
||||
Exit;
|
||||
end;
|
||||
until Opcode <> '';
|
||||
end;
|
||||
|
||||
const
|
||||
MEMPTR: array[TOperandSize] of string = ('byte ptr ', 'word ptr ', 'dword ptr ', 'qword ptr ', 'tbyte ptr ');
|
||||
OSTEXT: array[TOperandSize] of string = ('os8', 'os16', 'os32', 'os64', 'os80');
|
||||
|
||||
MEMPTR: array[TOperandSize] of string = ('byte ptr ', 'word ptr ', 'dword ptr ', 'qword ptr ', '', 'tbyte ptr ', '16byte ptr ');
|
||||
{$ifdef debug_OperandSize}
|
||||
OSTEXT: array[TOperandSize] of string = ('os8', 'os16', 'os32', 'os64', 'os48', 'os80', 'os128');
|
||||
{$endif}
|
||||
var
|
||||
BytesRead: Cardinal;
|
||||
S, Soper: String;
|
||||
n: Integer;
|
||||
HasMem: Boolean;
|
||||
begin
|
||||
BytesRead := 0;
|
||||
if not ReadProcessMemory(AProcess, Pointer(Address), @Code, SizeOf(Code), BytesRead) and (BytesRead = SizeOf(Code))
|
||||
then begin
|
||||
Log('Disassemble: Failed to read memory at %s, got %u bytes', [FormatAddress(Address), BytesRead]);
|
||||
ACode := '??';
|
||||
ACodeBytes := '??';
|
||||
Inc(Address);
|
||||
Exit;
|
||||
end;
|
||||
Code := AAddress;
|
||||
|
||||
Segment := '';
|
||||
Opcode := '';
|
||||
@ -3028,10 +3079,14 @@ begin
|
||||
begin
|
||||
if Operand[n].ByteCount = 0
|
||||
then S := Operand[n].Value
|
||||
else S := Format(Operand[n].Value, [HexValue(Code[CodeIdx], Operand[n].ByteCount, Operand[n].FormatFlags)]);
|
||||
else begin
|
||||
if Operand[n].ByteCount2 = 0
|
||||
then S := Format(Operand[n].Value, [HexValue(Code[CodeIdx], Operand[n].ByteCount, Operand[n].FormatFlags)])
|
||||
else S := Format(Operand[n].Value, [HexValue(Code[CodeIdx], Operand[n].ByteCount, Operand[n].FormatFlags), HexValue(Code[CodeIdx + Operand[n].ByteCount], Operand[n].ByteCount2, Operand[n].FormatFlags)])
|
||||
end;
|
||||
|
||||
if Soper <> '' then Soper := Soper + ',';
|
||||
if Operand[n].IsMemory
|
||||
if ofMemory in Operand[n].Flags
|
||||
then begin
|
||||
if (OperIdx = 1)
|
||||
// or (Operand[n].Size <> os32)
|
||||
@ -3042,6 +3097,7 @@ begin
|
||||
end
|
||||
else Soper := Soper + S;
|
||||
Inc(CodeIdx, Operand[n].ByteCount);
|
||||
Inc(CodeIdx, Operand[n].ByteCount2);
|
||||
end;
|
||||
{$ifdef debug_OperandSize}
|
||||
Soper := Soper + ' | ';
|
||||
@ -3052,9 +3108,9 @@ begin
|
||||
{$endif}
|
||||
|
||||
S := '';
|
||||
if preLock in Flags then S := S + '**lock:**';
|
||||
if preRep in Flags then S := S + '?rep:?';
|
||||
if preRepNE in Flags then S := S + '?repne:?';
|
||||
if preLock in Flags then S := S + '**lock**';
|
||||
if preRep in Flags then S := S + '?rep?';
|
||||
if preRepNE in Flags then S := S + '?repne?';
|
||||
S := S + Opcode;
|
||||
if not HasMem and (Segment <> '') then S := S + ' ?' + Segment + '?';
|
||||
ACode := S + ' ' + Soper;
|
||||
@ -3066,7 +3122,7 @@ begin
|
||||
S := S + HexStr(Code[n], 2);
|
||||
end;
|
||||
ACodeBytes := S;
|
||||
Inc(Address, CodeIdx);
|
||||
Inc(AAddress, CodeIdx);
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user