Ciao a tutti.
Ho problemi con il capire il metodo che sta chiamando una determinata routine.
E' dentro la virtual table (dichiarato "virtual" per intenderci).
Il GetCaller restituisce un indirizzo .. ma via assemble view noto che è il returnAddress della routine (a sto punto con un mov eax, [ebp+4] facevo lo stesso..)
function GetCaller(Level: integer = 0): Pointer;
var
idx: longint;
prevbp: Pointer;
caller_frame, caller_addr, bp: Pointer;
begin
inc(Level);
Result := nil;
bp := get_caller_frame(get_frame);
caller_addr := get_caller_addr(bp);
try
prevbp := bp - 1;
idx := 0;
while (bp > prevbp) and (idx < Level) do
begin
caller_addr := get_caller_addr(bp);
caller_frame := get_caller_frame(bp);
if (caller_addr = nil) then
break;
Inc(idx);
if caller_frame = nil then
break;
prevbp := bp;
bp := caller_frame;
end;
except
{ prevent endless dump if an exception occured }
end;
Result := caller_addr;
end;
class function TMyTestObject.MethodName(address: pointer): shortstring;
var
methodtable: PMethodNameTable;
i: dword;
ovmt: PVmt;
begin
ovmt := PVmt(self);
Result := '';
while assigned(ovmt) do
begin
methodtable := PMethodNameTable(ovmt^.vMethodTable);
if assigned(methodtable) then
begin
for i := 0 to methodtable^.Count - 1 do
if methodtable^.entries[i].addr = address then
begin
Result := methodtable^.entries[i].Name^;
exit;
end;
end;
ovmt := ovmt^.vParent;
end;
if (Result = '') then
raise EIllegalArgumentException.CreateFmt('Method with address %P not found', [address]);
end;
L'obiettivo è trovare il nome del metodo chiamante, in modo da poter andare a pescare un comportamento specifico da XML ... cose che piacciono molto a nomore ;)
Stilgar
function TMyObject.selectOne(params: array of const): IBusinessObject;
function extractMethodName(Source: string): string;
var
idx: integer;
iPos: longint;
begin
Source := Trim(Source);
iPos := Pos(' ', Source);
if iPos > 0 then
begin
Delete(Source, 1, iPos);
end;
iPos := Pos('_', Source);
while iPos > 0 do
begin
Delete(Source, 1, iPos);
iPos := Pos('_', Source);
end;
iPos := Pos(',', Source);
if iPos > 0 then
begin
Delete(Source, iPos, Length(Source));
end;
Result := Source;
end;
var
TargetName: string;
AStack: TStackTracePointers;
functionName, sourceName: ShortString;
sourceLine: longint;
element: TDOMElement;
begin
GetStackTracePointers(AStack);
functionName := extractMethodName(BackTraceStrFunc(AStack[0]));
SetLength(AStack, 0);
TargetName := DeclaredMethodName(functionName);
element := getSelectNode(TargetName);
Result := nil;
end;
DeclaredMethodName serve per trovare il giusto Case dal codice pascal ;)