mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
158 lines
4.5 KiB
ObjectPascal
158 lines
4.5 KiB
ObjectPascal
unit stacktrace2;
|
|
|
|
{$MODE Delphi}
|
|
|
|
interface
|
|
|
|
uses LCLIntf, sysutils, classes, symbolhandler, CEFuncProc, NewKernelHandler,
|
|
byteinterpreter, commonTypeDefs;
|
|
|
|
procedure seperatestacktraceline(s: string; var address: string; var bytes: string; var details: string);
|
|
procedure ce_stacktrace(esp: ptrUint; ebp: ptrUint; eip: ptrUint; stack: Pbytearray; sizeinbytes: integer; trace: tstrings; force4byteblocks: boolean=true; showmodulesonly: boolean=false; nosystemmodules:boolean=false; maxdepth:integer=0; ShowEBPinsteadOfESP: boolean=false);
|
|
|
|
implementation
|
|
|
|
uses StrUtils, ProcessHandlerUnit;
|
|
|
|
procedure seperatestacktraceline(s: string; var address: string; var bytes: string; var details: string);
|
|
var i,j: integer;
|
|
begin
|
|
//has 2 ' - ' occurances
|
|
i:=pos(' - ',s);
|
|
address:=copy(s,1,i-1);
|
|
|
|
j:=posex(' - ',s,i+3);
|
|
bytes:=copy(s,i+3,j-(i+3));
|
|
|
|
details:=copy(s,j+3,length(s)); //leftover
|
|
end;
|
|
|
|
procedure ce_stacktrace(esp: ptrUint; ebp: ptrUint; eip: ptrUint; stack: Pbytearray; sizeinbytes: integer; trace: tstrings; force4byteblocks: boolean=true; showmodulesonly: boolean=false; nosystemmodules:boolean=false; maxdepth:integer=0; ShowEBPinsteadOfESP: boolean=false);
|
|
{
|
|
ce_stacktrace will walk the provided stack trying to figure out functionnames ,passed strings and optional other data
|
|
esp must be aligned on a 4 byte boundary the first entry alignment but other entries will try to be forced to 4 byte alignment unless otherwise needed (double, string,...)
|
|
|
|
if eip is in a known function location this can help with the parameter naming (for the location of ebp)
|
|
esp is the first 4 byte of stack
|
|
|
|
nosystemmodules is only in effect when show moduleso only is enabled
|
|
}
|
|
var
|
|
alignedstack: pbytearray;
|
|
alignedstack32: PDwordArray absolute alignedstack;
|
|
alignedstack64: Puint64Array absolute alignedstack;
|
|
i: integer;
|
|
Entries: integer;
|
|
|
|
currentStackpos: ptruint;
|
|
currentStackValue: ptruint;
|
|
|
|
|
|
address: string;
|
|
value: string;
|
|
secondary: string;
|
|
v: TVariableType;
|
|
oldi: integer;
|
|
|
|
originalesp: ptruint;
|
|
offset: ptrint;
|
|
offsetstring: string;
|
|
pref: char;
|
|
begin
|
|
if processhandler.is64bit then
|
|
pref:='r'
|
|
else
|
|
pref:='e';
|
|
|
|
originalesp:=esp;
|
|
i:=esp mod processhandler.pointersize;
|
|
if i>0 then
|
|
begin
|
|
//unalligned
|
|
alignedstack:=stack+(processhandler.pointersize-i);
|
|
dec(sizeinbytes,processhandler.pointersize-i);
|
|
inc(esp,i);
|
|
end else alignedstack:=stack;
|
|
|
|
dec(sizeinbytes,sizeinbytes mod processhandler.pointersize); //so it's a full boundary
|
|
|
|
Entries:=sizeinbytes div processhandler.pointersize;
|
|
|
|
i:=0;
|
|
while i<entries do
|
|
begin
|
|
oldi:=i;
|
|
|
|
if not ShowEBPinsteadOfESP then
|
|
offsetstring:='('+pref+'sp+'+inttohex(esp-originalesp,1)+')'
|
|
else
|
|
begin
|
|
offset:=esp-ebp;
|
|
if offset<0 then
|
|
offsetstring:='('+pref+'bp-'+inttohex(-offset,1)+')'
|
|
else
|
|
offsetstring:='('+pref+'bp+'+inttohex(offset,1)+')';
|
|
end;
|
|
|
|
address:=inttohex(esp,8)+offsetstring;
|
|
|
|
|
|
if processhandler.is64bit then
|
|
begin
|
|
currentStackpos:=ptruint(@alignedstack64[i]);
|
|
value:=inttohex(alignedstack64[i],16);
|
|
currentStackValue:=ptruint(alignedstack64[i]);
|
|
end
|
|
else
|
|
begin
|
|
currentStackpos:=ptruint(@alignedstack32[i]);
|
|
value:=inttohex(alignedstack32[i],8);
|
|
currentStackValue:=ptruint(alignedstack32[i]);
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
v:=vtdword;
|
|
|
|
//figure out what alignedstack[i] is.
|
|
|
|
if showmodulesonly then
|
|
begin
|
|
if symhandler.inModule(currentStackValue) and ((not nosystemmodules) or (not symhandler.inSystemModule(currentStackValue))) then
|
|
v:=vtPointer
|
|
else
|
|
begin
|
|
inc(i);
|
|
inc(esp, (i-oldi)*processhandler.pointersize);
|
|
continue; //skip
|
|
end;
|
|
end
|
|
else
|
|
v:=FindTypeOfData(esp,pointer(currentstackpos),sizeinbytes-(i*processhandler.pointersize));
|
|
|
|
if v in [vtbyte..vtQword] then
|
|
begin
|
|
//override into pointersize type
|
|
if processhandler.is64bit then
|
|
v:=vtQword
|
|
else
|
|
v:=vtDword;
|
|
end;
|
|
|
|
secondary:=DataToString(@currentStackValue,processhandler.pointersize, v);
|
|
//optional: find the lengts of a string and increase i with the number of stack elements used in the string
|
|
inc(i);
|
|
|
|
|
|
trace.AddObject(address+' - '+value+' - '+secondary, pointer(esp));
|
|
if (maxdepth>0) and (trace.Count>=maxdepth) then exit;
|
|
|
|
inc(esp, (i-oldi)*processhandler.pointersize);
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
end.
|