mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-07-04 13:38:18 +02:00
FpDebug: fix for some missing stackframes
(cherry picked from commit 8da9f2d084
)
This commit is contained in:
parent
6ecf0f00f4
commit
70e8e1e211
@ -655,6 +655,8 @@ type
|
|||||||
|
|
||||||
function GetInstructionInfo(AnAddress: TDBGPtr): TDbgAsmInstruction; virtual; abstract;
|
function GetInstructionInfo(AnAddress: TDBGPtr): TDbgAsmInstruction; virtual; abstract;
|
||||||
function GetFunctionFrameInfo(AnAddress: TDBGPtr; out AnIsOutsideFrame: Boolean): Boolean; virtual;
|
function GetFunctionFrameInfo(AnAddress: TDBGPtr; out AnIsOutsideFrame: Boolean): Boolean; virtual;
|
||||||
|
function IsAfterCallInstruction(AnAddress: TDBGPtr): boolean; virtual;
|
||||||
|
function UnwindFrame(var AnAddress, AStackPtr, AFramePtr: TDBGPtr; AQuick: boolean): boolean; virtual;
|
||||||
|
|
||||||
property LastErrorWasMemReadErr: Boolean read GetLastErrorWasMemReadErr;
|
property LastErrorWasMemReadErr: Boolean read GetLastErrorWasMemReadErr;
|
||||||
property MaxInstructionSize: integer read GetMaxInstrSize; // abstract
|
property MaxInstructionSize: integer read GetMaxInstrSize; // abstract
|
||||||
@ -1875,6 +1877,17 @@ begin
|
|||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TDbgAsmDecoder.IsAfterCallInstruction(AnAddress: TDBGPtr): boolean;
|
||||||
|
begin
|
||||||
|
Result := True; // if we don't know, then assume yes
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDbgAsmDecoder.UnwindFrame(var AnAddress, AStackPtr,
|
||||||
|
AFramePtr: TDBGPtr; AQuick: boolean): boolean;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDbgInstance }
|
{ TDbgInstance }
|
||||||
|
|
||||||
|
|
||||||
@ -3299,6 +3312,7 @@ const
|
|||||||
MAX_FRAMES = 150000; // safety net
|
MAX_FRAMES = 150000; // safety net
|
||||||
var
|
var
|
||||||
Address, FrameBase, LastFrameBase, Dummy: QWord;
|
Address, FrameBase, LastFrameBase, Dummy: QWord;
|
||||||
|
PrevAddress, PrevFrameBase, PrevStackPtr: QWord;
|
||||||
Size, CountNeeded, IP, BP, CodeReadErrCnt, SP, i,
|
Size, CountNeeded, IP, BP, CodeReadErrCnt, SP, i,
|
||||||
PrevStmtAddressOffs: integer;
|
PrevStmtAddressOffs: integer;
|
||||||
AnEntry, NewEntry: TDbgCallstackEntry;
|
AnEntry, NewEntry: TDbgCallstackEntry;
|
||||||
@ -3310,6 +3324,37 @@ var
|
|||||||
Row: TDwarfCallFrameInformationRow;
|
Row: TDwarfCallFrameInformationRow;
|
||||||
CIE: TDwarfCIE;
|
CIE: TDwarfCIE;
|
||||||
CU: TDwarfCompilationUnit;
|
CU: TDwarfCompilationUnit;
|
||||||
|
|
||||||
|
procedure CheckFrame(var NextEntry: TDbgCallstackEntry; AForce: boolean = False);
|
||||||
|
begin
|
||||||
|
if (not AForce) and (NextEntry <> nil) and Process.Disassembler.IsAfterCallInstruction(Address) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if not Process.Disassembler.UnwindFrame(PrevAddress, PrevStackPtr, PrevFrameBase, False) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if (NextEntry <> nil) and
|
||||||
|
(Address = PrevAddress) and (FrameBase = PrevFrameBase) and (StackPtr = PrevStackPtr)
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
if not Process.Disassembler.IsAfterCallInstruction(PrevAddress) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
Address := PrevAddress;
|
||||||
|
FrameBase := PrevFrameBase;
|
||||||
|
StackPtr := PrevStackPtr;
|
||||||
|
NextEntry.Free;
|
||||||
|
NextEntry := TDbgCallstackEntry.create(Self, NextIdx, FrameBase, Address);
|
||||||
|
NextEntry.RegisterValueList.DbgRegisterAutoCreate[nIP].SetValue(Address, IntToStr(Address),Size, IP);
|
||||||
|
NextEntry.RegisterValueList.DbgRegisterAutoCreate[nBP].SetValue(FrameBase, IntToStr(FrameBase),Size, BP);
|
||||||
|
NextEntry.RegisterValueList.DbgRegisterAutoCreate[nSP].SetValue(StackPtr, IntToStr(StackPtr),Size, SP);
|
||||||
|
LastFrameBase := FrameBase;
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
if LastFrameBase > 0 then
|
||||||
|
LastFrameBase := LastFrameBase - 1;
|
||||||
|
{$POP}
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
// TODO: use AFrameRequired // check if already partly done
|
// TODO: use AFrameRequired // check if already partly done
|
||||||
if FCallStackEntryList = nil then
|
if FCallStackEntryList = nil then
|
||||||
@ -3385,8 +3430,13 @@ begin
|
|||||||
CodeReadErrCnt := 0;
|
CodeReadErrCnt := 0;
|
||||||
while (CountNeeded > 0) do
|
while (CountNeeded > 0) do
|
||||||
begin
|
begin
|
||||||
|
PrevAddress := Address;
|
||||||
|
PrevFrameBase := FrameBase;
|
||||||
|
PrevStackPtr := StackPtr;
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
if (Process.DbgInfo as TFpDwarfInfo).FindCallFrameInfo(Address - PrevStmtAddressOffs, CIE, Row) and
|
if (Process.DbgInfo as TFpDwarfInfo).FindCallFrameInfo(Address - PrevStmtAddressOffs, CIE, Row) and
|
||||||
TDwarfCallFrameInformation.TryObtainNextCallFrame(AnEntry, CIE, Size, NextIdx, Self, Row, Process, NewEntry)
|
TDwarfCallFrameInformation.TryObtainNextCallFrame(AnEntry, CIE, Size, NextIdx, Self, Row, Process, NewEntry)
|
||||||
|
{$POP}
|
||||||
then begin
|
then begin
|
||||||
PrevStmtAddressOffs := 1;
|
PrevStmtAddressOffs := 1;
|
||||||
if not Assigned(NewEntry) then begin
|
if not Assigned(NewEntry) then begin
|
||||||
@ -3396,7 +3446,6 @@ begin
|
|||||||
Break;
|
Break;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
FCallStackEntryList.Add(NewEntry);
|
|
||||||
Address := NewEntry.AnAddress;
|
Address := NewEntry.AnAddress;
|
||||||
StackReg := NewEntry.RegisterValueList.FindRegisterByDwarfIndex(SP);
|
StackReg := NewEntry.RegisterValueList.FindRegisterByDwarfIndex(SP);
|
||||||
FrameReg := NewEntry.RegisterValueList.FindRegisterByDwarfIndex(BP);
|
FrameReg := NewEntry.RegisterValueList.FindRegisterByDwarfIndex(BP);
|
||||||
@ -3406,6 +3455,8 @@ begin
|
|||||||
FrameBase := FrameReg.FNumValue;
|
FrameBase := FrameReg.FNumValue;
|
||||||
end;
|
end;
|
||||||
AnEntry := NewEntry;
|
AnEntry := NewEntry;
|
||||||
|
CheckFrame(NewEntry);
|
||||||
|
FCallStackEntryList.Add(NewEntry);
|
||||||
Dec(CountNeeded);
|
Dec(CountNeeded);
|
||||||
inc(NextIdx);
|
inc(NextIdx);
|
||||||
If (NextIdx > MAX_FRAMES) then
|
If (NextIdx > MAX_FRAMES) then
|
||||||
@ -3416,6 +3467,33 @@ begin
|
|||||||
end;
|
end;
|
||||||
PrevStmtAddressOffs := 1;
|
PrevStmtAddressOffs := 1;
|
||||||
|
|
||||||
|
if Process.Disassembler.UnwindFrame(PrevAddress, PrevStackPtr, PrevFrameBase, True) and
|
||||||
|
Process.Disassembler.IsAfterCallInstruction(PrevAddress)
|
||||||
|
then begin
|
||||||
|
Address := PrevAddress;
|
||||||
|
FrameBase := PrevFrameBase;
|
||||||
|
StackPtr := PrevStackPtr;
|
||||||
|
AnEntry := TDbgCallstackEntry.create(Self, NextIdx, FrameBase, Address);
|
||||||
|
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nIP].SetValue(Address, IntToStr(Address),Size, IP);
|
||||||
|
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nBP].SetValue(FrameBase, IntToStr(FrameBase),Size, BP);
|
||||||
|
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nSP].SetValue(StackPtr, IntToStr(StackPtr),Size, SP);
|
||||||
|
FCallStackEntryList.Add(AnEntry);
|
||||||
|
Dec(CountNeeded);
|
||||||
|
inc(NextIdx);
|
||||||
|
CodeReadErrCnt := 0;
|
||||||
|
If (NextIdx > MAX_FRAMES) then
|
||||||
|
break;
|
||||||
|
LastFrameBase := FrameBase;
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
if LastFrameBase > 0 then
|
||||||
|
LastFrameBase := LastFrameBase - 1;
|
||||||
|
{$POP}
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
Address := PrevAddress;
|
||||||
|
FrameBase := PrevFrameBase;
|
||||||
|
StackPtr := PrevStackPtr;
|
||||||
|
|
||||||
if (FrameBase <> 0) and (FrameBase > LastFrameBase)
|
if (FrameBase <> 0) and (FrameBase > LastFrameBase)
|
||||||
then begin
|
then begin
|
||||||
if StackPtr = 0 then
|
if StackPtr = 0 then
|
||||||
@ -3446,7 +3524,8 @@ begin
|
|||||||
else begin
|
else begin
|
||||||
{$PUSH}{$R-}{$Q-}
|
{$PUSH}{$R-}{$Q-}
|
||||||
StackPtr := StackPtr + 1 * Size; // After popping return-addr from "StackPtr"
|
StackPtr := StackPtr + 1 * Size; // After popping return-addr from "StackPtr"
|
||||||
LastFrameBase := LastFrameBase - 1; // Make the loop think thas LastFrameBase was smaller
|
if LastFrameBase > 0 then
|
||||||
|
LastFrameBase := LastFrameBase - 1; // Make the loop think thas LastFrameBase was smaller
|
||||||
{$POP}
|
{$POP}
|
||||||
// last stack has no frame
|
// last stack has no frame
|
||||||
//AnEntry.RegisterValueList.DbgRegisterAutoCreate[nBP].SetValue(0, '0',Size, BP);
|
//AnEntry.RegisterValueList.DbgRegisterAutoCreate[nBP].SetValue(0, '0',Size, BP);
|
||||||
@ -3463,6 +3542,7 @@ begin
|
|||||||
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nIP].SetValue(Address, IntToStr(Address),Size, IP);
|
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nIP].SetValue(Address, IntToStr(Address),Size, IP);
|
||||||
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nBP].SetValue(FrameBase, IntToStr(FrameBase),Size, BP);
|
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nBP].SetValue(FrameBase, IntToStr(FrameBase),Size, BP);
|
||||||
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nSP].SetValue(StackPtr, IntToStr(StackPtr),Size, SP);
|
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nSP].SetValue(StackPtr, IntToStr(StackPtr),Size, SP);
|
||||||
|
CheckFrame(AnEntry, FrameBase < StackPtr);
|
||||||
FCallStackEntryList.Add(AnEntry);
|
FCallStackEntryList.Add(AnEntry);
|
||||||
Dec(CountNeeded);
|
Dec(CountNeeded);
|
||||||
inc(NextIdx);
|
inc(NextIdx);
|
||||||
@ -3471,7 +3551,14 @@ begin
|
|||||||
break;
|
break;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
Break;
|
begin
|
||||||
|
AnEntry := nil;
|
||||||
|
CheckFrame(AnEntry);
|
||||||
|
if AnEntry <> nil then
|
||||||
|
FCallStackEntryList.Add(AnEntry)
|
||||||
|
else
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
if CountNeeded > 0 then // there was an error / not possible to read more frames
|
if CountNeeded > 0 then // there was an error / not possible to read more frames
|
||||||
FCallStackEntryList.SetHasReadAllAvailableFrames;
|
FCallStackEntryList.SetHasReadAllAvailableFrames;
|
||||||
|
@ -568,6 +568,9 @@ type
|
|||||||
|
|
||||||
function GetFunctionFrameInfo(AnAddress: TDBGPtr; out
|
function GetFunctionFrameInfo(AnAddress: TDBGPtr; out
|
||||||
AnIsOutsideFrame: Boolean): Boolean; override;
|
AnIsOutsideFrame: Boolean): Boolean; override;
|
||||||
|
function IsAfterCallInstruction(AnAddress: TDBGPtr): boolean; override;
|
||||||
|
// Only Modify the values if result is true
|
||||||
|
function UnwindFrame(var AnAddress, AStackPtr, AFramePtr: TDBGPtr; AQuick: boolean): boolean; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -5172,6 +5175,288 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TX86AsmDecoder.IsAfterCallInstruction(AnAddress: TDBGPtr): boolean;
|
||||||
|
const
|
||||||
|
MAX_RET_LEN = 10;
|
||||||
|
var
|
||||||
|
BytesRead: Cardinal;
|
||||||
|
i: Integer;
|
||||||
|
instr: TDbgAsmInstruction;
|
||||||
|
begin
|
||||||
|
BytesRead := MAX_RET_LEN;
|
||||||
|
Result := (AnAddress > MAX_RET_LEN) and ReadCodeAt(AnAddress - MAX_RET_LEN, BytesRead) and
|
||||||
|
(BytesRead = MAX_RET_LEN);
|
||||||
|
if not Result then begin
|
||||||
|
BytesRead := 5;
|
||||||
|
Result := (AnAddress > MAX_RET_LEN) and ReadCodeAt(AnAddress - MAX_RET_LEN, BytesRead) and
|
||||||
|
(BytesRead = MAX_RET_LEN);
|
||||||
|
end;
|
||||||
|
if not Result then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
// can be a false positive
|
||||||
|
Result := (FCodeBin[MAX_RET_LEN-3] in [$9A, $E8]) or (FCodeBin[MAX_RET_LEN-5] in [$9A, $E8]);
|
||||||
|
if Result then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
for i := 2 to 6 do
|
||||||
|
if (FCodeBin[MAX_RET_LEN - i] = $FF) and
|
||||||
|
(FCodeBin[MAX_RET_LEN + 1 - i] and $38 in [$10, $18])
|
||||||
|
then begin
|
||||||
|
instr := GetInstructionInfo(AnAddress - i);
|
||||||
|
Result := instr.IsCallInstruction;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
if (FCodeBin[MAX_RET_LEN-10] = $FF) and
|
||||||
|
(FCodeBin[MAX_RET_LEN + 1 - 10] and $38 in [$10, $18])
|
||||||
|
then begin
|
||||||
|
instr := GetInstructionInfo(AnAddress-10);
|
||||||
|
Result := instr.IsCallInstruction;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TX86AsmDecoder.UnwindFrame(var AnAddress, AStackPtr,
|
||||||
|
AFramePtr: TDBGPtr; AQuick: boolean): boolean;
|
||||||
|
|
||||||
|
function IsRegister(Val, Reg: String): boolean;
|
||||||
|
begin
|
||||||
|
Result := (Length(val) >= 2) and (val[1] in ['r', 'e']) and (strlcomp(@Val[2], PChar(Reg), Length(Reg)) = 0);
|
||||||
|
end;
|
||||||
|
function RegisterSize(Reg: String): Cardinal;
|
||||||
|
begin
|
||||||
|
Result := 4;
|
||||||
|
if (Reg <> '') and (Reg[1] = 'r') then
|
||||||
|
Result := 8;
|
||||||
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
MAX_SEARCH_ADDR = 1000;
|
||||||
|
MAX_SEARCH_CNT = 80;
|
||||||
|
var
|
||||||
|
NewAddr, NewStack, NewFrame, MaxAddr, StartStack: TDBGPtr;
|
||||||
|
Cnt: Integer;
|
||||||
|
instr: TX86AsmInstruction;
|
||||||
|
RSize: Cardinal;
|
||||||
|
Val: Int64;
|
||||||
|
CurAddr: PByte;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
NewAddr := AnAddress;
|
||||||
|
NewStack := AStackPtr;
|
||||||
|
StartStack := AStackPtr;
|
||||||
|
NewFrame := AFramePtr;
|
||||||
|
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
MaxAddr := AnAddress + MAX_SEARCH_ADDR;
|
||||||
|
{$POP}
|
||||||
|
Cnt := MAX_SEARCH_CNT;
|
||||||
|
if AQuick then Cnt := 10;
|
||||||
|
|
||||||
|
while (NewAddr < MaxAddr) and (Cnt > 0) do begin
|
||||||
|
dec(Cnt);
|
||||||
|
instr := TX86AsmInstruction(GetInstructionInfo(NewAddr));
|
||||||
|
if instr.InstructionLength <= 0 then
|
||||||
|
exit;
|
||||||
|
NewAddr := NewAddr + instr.InstructionLength;
|
||||||
|
CurAddr := @instr.FCodeBin[0];
|
||||||
|
|
||||||
|
case instr.X86OpCode of
|
||||||
|
OPret:
|
||||||
|
begin
|
||||||
|
if instr.X86Instruction.OperCnt > 1 then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
Val := 0;
|
||||||
|
if instr.X86Instruction.OperCnt = 1 then
|
||||||
|
Val := ValueFromMem(CurAddr[Instr.X86Instruction.Operand[1].CodeIndex], Instr.X86Instruction.Operand[1].ByteCount, Instr.X86Instruction.Operand[1].FormatFlags);
|
||||||
|
NewAddr := 0;
|
||||||
|
if FProcess.Mode = dm32 then begin
|
||||||
|
if not FProcess.ReadData(NewStack, 4, NewAddr, RSize) then
|
||||||
|
exit;
|
||||||
|
inc(NewStack, 4 + Val);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if not FProcess.ReadData(NewStack, 8, NewAddr, RSize) then
|
||||||
|
exit;
|
||||||
|
inc(NewStack, 8 + Val);
|
||||||
|
end;
|
||||||
|
Result := True;
|
||||||
|
AnAddress := NewAddr;
|
||||||
|
AStackPtr := NewStack;
|
||||||
|
AFramePtr := NewFrame;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
OPpush:
|
||||||
|
begin
|
||||||
|
if AQuick then
|
||||||
|
exit;
|
||||||
|
if (instr.X86Instruction.OperCnt <> 1) or
|
||||||
|
IsRegister(instr.X86Instruction.Operand[1].Value, 'bp') or
|
||||||
|
IsRegister(instr.X86Instruction.Operand[1].Value, 'sp')
|
||||||
|
then begin
|
||||||
|
exit; // false
|
||||||
|
end;
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
NewStack := NewStack - RegisterSize(instr.X86Instruction.Operand[1].Value);
|
||||||
|
{$POP}
|
||||||
|
end;
|
||||||
|
OPpusha, OPpushf:
|
||||||
|
exit; // false
|
||||||
|
OPpopa, OPpopad:
|
||||||
|
exit; // false
|
||||||
|
OPpop:
|
||||||
|
begin
|
||||||
|
if instr.X86Instruction.OperCnt <> 1 then
|
||||||
|
exit;
|
||||||
|
if not(instr.X86Instruction.Operand[1].Value[1] in ['e', 'r'])
|
||||||
|
then
|
||||||
|
exit; // false
|
||||||
|
if IsRegister(instr.X86Instruction.Operand[1].Value, 'bp')
|
||||||
|
then begin
|
||||||
|
if NewStack < StartStack then
|
||||||
|
exit;
|
||||||
|
NewFrame := 0;
|
||||||
|
RSize := RegisterSize(instr.X86Instruction.Operand[1].Value);
|
||||||
|
if not FProcess.ReadData(NewStack, RSize, NewFrame, RSize) then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
NewStack := NewStack + RegisterSize(instr.X86Instruction.Operand[1].Value);
|
||||||
|
{$POP}
|
||||||
|
end;
|
||||||
|
OPleave:
|
||||||
|
begin
|
||||||
|
NewStack := NewFrame;
|
||||||
|
NewFrame := 0;
|
||||||
|
if FProcess.Mode = dm32 then begin
|
||||||
|
if not FProcess.ReadData(NewStack, 4, NewFrame, RSize) then
|
||||||
|
exit;
|
||||||
|
inc(NewStack, 4);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if not FProcess.ReadData(NewStack, 8, NewFrame, RSize) then
|
||||||
|
exit;
|
||||||
|
inc(NewStack, 8);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
OPmov:
|
||||||
|
begin
|
||||||
|
if instr.X86Instruction.OperCnt <> 2 then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if IsRegister(instr.X86Instruction.Operand[1].Value, 'sp')
|
||||||
|
then begin
|
||||||
|
if (not IsRegister(instr.X86Instruction.Operand[2].Value, 'bp')) or
|
||||||
|
(Instr.X86Instruction.Operand[2].ByteCount <> 0) or
|
||||||
|
(Instr.X86Instruction.Operand[2].ByteCount2 <> 0) or
|
||||||
|
(ofMemory in Instr.X86Instruction.Operand[2].Flags)
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
NewStack := NewFrame;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
OPlea:
|
||||||
|
begin
|
||||||
|
if instr.X86Instruction.OperCnt <> 2 then
|
||||||
|
exit;
|
||||||
|
if IsRegister(instr.X86Instruction.Operand[1].Value, 'bp')
|
||||||
|
then begin
|
||||||
|
if (not IsRegister(instr.X86Instruction.Operand[2].Value, 'bp%s')) or
|
||||||
|
(Instr.X86Instruction.Operand[2].ByteCount = 0) or
|
||||||
|
(Instr.X86Instruction.Operand[2].ByteCount2 <> 0) or
|
||||||
|
not(ofMemory in Instr.X86Instruction.Operand[2].Flags)
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
Val := ValueFromMem(CurAddr[Instr.X86Instruction.Operand[2].CodeIndex], Instr.X86Instruction.Operand[2].ByteCount, Instr.X86Instruction.Operand[2].FormatFlags);
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
NewFrame := NewFrame + Val;
|
||||||
|
{$POP}
|
||||||
|
end;
|
||||||
|
if IsRegister(instr.X86Instruction.Operand[1].Value, 'sp')
|
||||||
|
then begin
|
||||||
|
if (Instr.X86Instruction.Operand[2].ByteCount = 0) or
|
||||||
|
(Instr.X86Instruction.Operand[2].ByteCount2 <> 0) or
|
||||||
|
not(ofMemory in Instr.X86Instruction.Operand[2].Flags)
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if (IsRegister(instr.X86Instruction.Operand[2].Value, 'sp%s')) then begin
|
||||||
|
Val := ValueFromMem(CurAddr[Instr.X86Instruction.Operand[2].CodeIndex], Instr.X86Instruction.Operand[2].ByteCount, Instr.X86Instruction.Operand[2].FormatFlags);
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
NewStack := NewStack + Val;
|
||||||
|
{$POP}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (IsRegister(instr.X86Instruction.Operand[2].Value, 'bp%s')) then begin
|
||||||
|
Val := ValueFromMem(CurAddr[Instr.X86Instruction.Operand[2].CodeIndex], Instr.X86Instruction.Operand[2].ByteCount, Instr.X86Instruction.Operand[2].FormatFlags);
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
NewStack := NewFrame + Val;
|
||||||
|
{$POP}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
OPadd:
|
||||||
|
begin
|
||||||
|
if instr.X86Instruction.OperCnt <> 2 then
|
||||||
|
exit;
|
||||||
|
if IsRegister(instr.X86Instruction.Operand[1].Value, 'sp')
|
||||||
|
then begin
|
||||||
|
if (instr.X86Instruction.Operand[2].Value <> '%s') or
|
||||||
|
(Instr.X86Instruction.Operand[2].ByteCount = 0) or
|
||||||
|
(Instr.X86Instruction.Operand[2].ByteCount2 <> 0) or
|
||||||
|
(ofMemory in Instr.X86Instruction.Operand[2].Flags)
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
Val := ValueFromMem(CurAddr[Instr.X86Instruction.Operand[2].CodeIndex], Instr.X86Instruction.Operand[2].ByteCount, Instr.X86Instruction.Operand[2].FormatFlags);
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
NewStack := NewStack + Val;
|
||||||
|
{$POP}
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
OPjmp:
|
||||||
|
begin
|
||||||
|
if AQuick then
|
||||||
|
exit;
|
||||||
|
if instr.X86Instruction.OperCnt <> 1 then
|
||||||
|
exit;
|
||||||
|
if (instr.X86Instruction.Operand[1].Value <> '%s') then
|
||||||
|
exit; // false
|
||||||
|
if (Instr.X86Instruction.Operand[1].ByteCount = 0) or
|
||||||
|
(Instr.X86Instruction.Operand[1].ByteCount > 2) or
|
||||||
|
(Instr.X86Instruction.Operand[1].ByteCount2 <> 0)
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
Val := ValueFromMem(CurAddr[Instr.X86Instruction.Operand[1].CodeIndex], Instr.X86Instruction.Operand[1].ByteCount, Instr.X86Instruction.Operand[1].FormatFlags);
|
||||||
|
if Val <= 0 then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
{$PUSH}{$R-}{$Q-}
|
||||||
|
NewAddr := NewAddr + Val
|
||||||
|
{$POP}
|
||||||
|
end;
|
||||||
|
OPjmpe, OPint, OPint1, OPint3:
|
||||||
|
exit; // false
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if (instr.X86Instruction.OperCnt >= 1) and
|
||||||
|
(not(ofMemory in Instr.X86Instruction.Operand[1].Flags)) and
|
||||||
|
( IsRegister(instr.X86Instruction.Operand[1].Value, 'bp') or
|
||||||
|
IsRegister(instr.X86Instruction.Operand[1].Value, 'sp')
|
||||||
|
)
|
||||||
|
then begin
|
||||||
|
exit; // false
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
DBG_WARNINGS := DebugLogger.FindOrRegisterLogGroup('DBG_WARNINGS' {$IFDEF DBG_WARNINGS} , True {$ENDIF} );
|
DBG_WARNINGS := DebugLogger.FindOrRegisterLogGroup('DBG_WARNINGS' {$IFDEF DBG_WARNINGS} , True {$ENDIF} );
|
||||||
|
@ -206,6 +206,7 @@ function QuickUtf8UpperCase(const AText: String): String;
|
|||||||
function QuickUtf8LowerCase(const AText: String): String;
|
function QuickUtf8LowerCase(const AText: String): String;
|
||||||
|
|
||||||
function AlignPtr(Src: Pointer; Alignment: Byte): Pointer;
|
function AlignPtr(Src: Pointer; Alignment: Byte): Pointer;
|
||||||
|
function ValueFromMem(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): Int64;
|
||||||
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
||||||
function FormatAddress(const AAddress): String;
|
function FormatAddress(const AAddress): String;
|
||||||
|
|
||||||
@ -436,6 +437,28 @@ begin
|
|||||||
Result := HexValue(AAddress, DBGPTRSIZE[GMode], [hvfIncludeHexchar]);
|
Result := HexValue(AAddress, DBGPTRSIZE[GMode], [hvfIncludeHexchar]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function ValueFromMem(const AValue; ASize: Byte; AFlags: THexValueFormatFlags
|
||||||
|
): Int64;
|
||||||
|
var
|
||||||
|
p: PByte;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
if ASize > 8 then
|
||||||
|
Exit;
|
||||||
|
if ASize = 0 then
|
||||||
|
Exit;
|
||||||
|
|
||||||
|
p := @AValue;
|
||||||
|
if p[ASize - 1] < $80
|
||||||
|
then Exclude(AFlags, hvfSigned);
|
||||||
|
|
||||||
|
if hvfSigned in AFlags
|
||||||
|
then Result := -1
|
||||||
|
else Result := 0;
|
||||||
|
|
||||||
|
Move(AValue, Result, ASize);
|
||||||
|
end;
|
||||||
|
|
||||||
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
||||||
var
|
var
|
||||||
i: Int64;
|
i: Int64;
|
||||||
|
Loading…
Reference in New Issue
Block a user