Autor Beitrag
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Fr 11.03.16 20:16 
Hi,
ich möchte gerne einen stack-Trace des Call-stacks in einer x86-Anwendung erstellen.
Mir ist bewusst, dass die Jedi-Libraries das können, ich möchte das aber gerne selber machen.
Ich weiss schon so ungefähr, dass man sich an den return-calls entlanghangelt, und dabei ausnutzt, dass alle Funktionen diese Zeile haben
ausblenden Quelltext
1:
2:
0 D40224 55                               push ebp
1 D40225 8BEC                             mov ebp, esp

Dass bedeuted, man muss quasi immer den nächsten ebp ermitteln, und dann den return-pointer finden.
Der stack sollte an der stelle dann doch so aussehen:

ausblenden Quelltext
1:
2:
3:
4:
xxxx
return-pointer
alter ebp
Lokale variablen   <--- Dahin zeigt der neue ebp

d.h. ich benutze den ebp, um den alten ebp zu ermitteln und hangele mich da durch und ermittele jedes mal die return-pointer. Der sollte dann also an [ebp+8] liegen.
Wie sieht dass dan in der Praxis aus? Mir fehlt da so ein bisschen der ansatz. Hat jemand so etwas schonmal gemacht und kann mir da ein paar code-Zeilen (bzw. asm-Zeilen) liefern, mit denen ich anfangen kann?
Ich möchte jetzt nicht unbedingt fertigen Code, sondern eher einen Ansatz, wie man das ganze angeht.
lg Boldar
Boldar Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Do 17.03.16 12:21 
Ich habs jetzt hinbekommen, falls es jemanden interessiert. Es war eigentlich recht einfach, wenn man erstmal drauf kommt:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
function _isBadReadPtr (p: pointer;size: integer):boolean;
var
  dw: SIZE_T;
  mbi: windows.MEMORY_BASIC_INFORMATION;
begin
  result := false;
  dw := Virtualquery (p, mbi, sizeof (mbi));
  result :=
        (mbi.Protect=PAGE_READONLY         )or
        (mbi.Protect=PAGE_READWRITE        )or
        (mbi.Protect=PAGE_WRITECOPY        )or
        (mbi.Protect=PAGE_EXECUTE_READ     )or
        (mbi.Protect=PAGE_EXECUTE_READWRITE)or
        (mbi.Protect=PAGE_EXECUTE_WRITECOPY);
  if (mbi.Protect = PAGE_GUARD   ) then result := false;
  if (mbi.Protect = PAGE_NOACCESS) then result := false;
  result := not result;
end;

function GetCallStackTrace: AnsiString;
var
    ret, stackwalk: ^pointer;
    conter: integer;
begin
    asm
        mov stackwalk, ebp
    end;
    while Cardinal(stackwalk^) <> 0 do begin
        ret := stackwalk;
        Inc(ret);
        if _isBadReadPtr(ret, 8then break;
        if _isBadReadPtr(stackwalk, 8then break;
        result := result + inspectfunc(ret^);
        stackwalk := stackwalk^;
    end;
end;

Für diesen Beitrag haben gedankt: SMO