Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: Stilgar - Maggio 08, 2013, 02:31:01 pm

Titolo: Stack e FrameBuffer
Inserito da: Stilgar - Maggio 08, 2013, 02:31:01 pm
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..)
Codice: [Seleziona]
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;
Codice: [Seleziona]
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
Titolo: Re:Stack e FrameBuffer
Inserito da: nomorelogic - Maggio 08, 2013, 05:34:13 pm
quindi vuoi cercare nel call stack se non ho capito male
qua non ti so essere d'aiuto ma se è così puoi vedere se trovi uno spunto qua
http://www.freepascal.org/docs-html/rtl/system/dumpexceptionbacktrace.html
Titolo: [risolto] Re:Stack e FrameBuffer
Inserito da: Stilgar - Maggio 08, 2013, 05:44:29 pm
Codice: [Seleziona]
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 ;)