GNT sans publicité, site mobile, fonctionnalitées exclusives...

Recuperer la pile de son programme

Le
yarocco
Salut,
J'ai un nouveau probleme :)
Je voudrais recuperer la pile de mon programme.
Pour ca, je suis alle recuperer l'exemple poste par Arnaud Debaene mais
ca ne marche pas

Donc, je vous poste ici mon code en esperant que vous puissiez m'aider :)

3 fonctions :
MyGetProcAddress : Retourne les adresses des fonctions
SymFunctionTableAccess64 et SymGetModuleBase64 (je pense que mon pb
vient de la, enfin des parametres dans StackWalk)
ManewFonction : fonction appelle lors de CreateThread et qui est cense
recuper la pile
Button4Click : procedure executee lors du Click sur un bouton (il faut
partir de la pour lire le code)

function MyGetProcAddress(NbrFunc: integer): Pointer;
var
Instance: Hwnd;
begin
//Normalement, rien d'anormal dans cette fonction (niveau code)
//Peut etre du point de vue logique (il ne faut pas etre pas les
// chargees ?)
Instance := LoadLibrary('DbgHelp.dll');
if Instance = 0 then
begin
MessageBox(0, 'Impossible de chager la DLL : DbgHelp.dll', 'Erreur
de chargement',
MB_OK or MB_ICONERROR);
Result := nil;
Exit;
end;

if NbrFunc = 1 then
Result := GetProcAddress(Instance, 'SymFunctionTableAccess64')
else Result := GetProcAddress(Instance, 'SymGetModuleBase64');
end;

function ManewFonction(param: Pointer): Boolean;
var
Contexte : CONTEXT;
StackFrame : TSTACKFRAME64;
Liste : TStringList;
Dbg : TDbgDebugger; //Implementation perso de DbgHelp car Borland ne
l'a pas mis !
Cpt: Integer;
MonThr : Cardinal;
begin
Dbg := TDbgDebugger.Create;
Liste := TStringList.Create;
MonThr := Form1.HandleThread; //J'ai essaye avec GetCurrentThread,
ca passe pas non plus.
//Petit PS: j'avais essaye de passer le pointeur de HandleThread par
le Param, mais ca passe pas,
//Savez vous pourquoi ??

//Suspend le thread pour lire
SuspendThread(MonThr);

//Recupere le context
Contexte.ContextFlags := CONTEXT_FULL;
if GetThreadContext(MonThr, Contexte) = False then
begin
//Si je ne fais pas un GetThreadContext sur le GetCurrentThread, je
n'arrive jamais a l'avoir !
MessageBox(0, 'GetThreadContext echoue', 'Erreur', Mb_OK or
Mb_ICONERROR);
MessageBox(0, PChar(SysErrorMessage(GetLastError())), 'Erreur',
Mb_OK or Mb_ICONERROR); //Donne le message d'erreur en clair
end;

//Remplit de 0 la structure
FillChar(StackFrame, SizeOf(TSTACKFRAME64), #0);

// Initilaise le context pour la 1ere fois (special x86)
StackFrame.AddrPC.Offset := Contexte.Eip;
StackFrame.AddrPC.Mode := AddrModeFlat;
StackFrame.AddrStack.Offset := Contexte.Esp;
StackFrame.AddrStack.Mode := AddrModeFlat;
StackFrame.AddrFrame.Offset := Contexte.Ebp;
StackFrame.AddrFrame.Mode := AddrModeFlat;

//Creer un Compteur pour voir le nombre de lignes sur la pile
Cpt :=0;

//Boucle pour recupere la pile
//Je pense donc que le pb vient des
// - PFunctionTableAccessProc64(MyGetProcAddress(1)) - Pointe vers la
// fonction de DbgHelp
// - PGetModuleBaseProc64(MyGetProcAddress(2)) ->Pointe vers la
// fonction de DbgHelp
While Dbg.StackWalk64(IMAGE_FILE_MACHINE_I386, GetCurrentProcess, MonThr,
@StackFrame, @Contexte, nil,
PFunctionTableAccessProc64(MyGetProcAddress(1)),
PGetModuleBaseProc64(MyGetProcAddress(2)), nil) = True do
begin
Liste.Add('Offset : ' + IntToHex(StackFrame.AddrPC.Offset, 8));
Inc(Cpt);
//if Cpt >= 10000 then Break; //Si je ne met pas ca, je suis dans
une boucle infinie !
if StackFrame.AddrPC.Offset = 0 then Break;
end;

//Sauvegarde le fichier
Liste.Add(IntToStr(Cpt));
Liste.Add('Fini stackWalk');
Liste.SaveToFile('C:\Stack.txt');

Result := True; //J'en vois pas l'interet mais ils renvoient tous
True pour cette fonction
//sur les exmples vus

//Voir le resultat sur ma fiche de delphi
Form1.ListBox1.Items := Liste;

//Destruction des objets utilises
Dbg.Free;
Liste.Free;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
HandleEvent, Newthread : Hwnd;
begin
//J'ai essaye de traduire le code de Arnaud Debaene et il avait
utilise un Event avec le WaitForSingleObject
HandleEvent := CreateEvent(nil, False, False, nil);
if Handleevent = 0 then
begin
MessageBox(0, 'Handle 0 pour Event', 'Erreur', Mb_OK or Mb_ICONERROR);
Exit;
end;

if DuplicateHandle(GetCurrentProcess, GetCurrentThread,
GetCurrentProcess, @HandleThread,
0, False, DUPLICATE_SAME_ACCESS) = False then
begin
MessageBox(0, 'DuplicateHandle non reussi', 'Erreur', Mb_OK or
Mb_ICONERROR);
Exit;
end;

NewThread := CreateThread(nil, 0, @MaNewFonction, nil, 0, thread_id);
if NewThread = 0 then
begin
MessageBox(0, 'Handle 0 pour NewThread', 'Erreur', Mb_OK or
Mb_ICONERROR);
Exit;
end;

//WaitForSingleObject(HandleEvent, INFINITE); //Mis en commentaire
car me fais faire une boucle infinie
//A moins que sauver la pile ne prenne plus d'une minute ?!
CloseHandle(NewThread);
CloseHandle(HandleThread);
end;

Il faut partir du Button4Click :)
Je sais que le nom des fonctions n'est pas tres explicites mais je suis
en train de tester, alors bonj'ai pas encore de mise en forme
J'ai essaye de detailler les differents problemes au fur et a mesure
dans les commentaires, si vous ne comprenez pas quelque chose, n'hesitez
pas a me demander.

PS : si vous voulez voir mon implementation de DbgHelp (au cas ou vous
ne detectez pas de grosse erreur) : glayag.free.fr/H_DbgHelp.pas
Lire les 18 réponses

Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 4
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
dark poulpo
Le #9722931
ya une astuce simple pour la pile: sprintf(dest,"%....."); comme ta pas mis
de variable apres la constante, il va lire la pile actuelle

sinon, fait le en asm se serait plus simple pour la lire.


--
-----
http://dark.freezee.org/
- Dark Update v1.0
- Dark Emule v0.44b r4
- Dark Desktop 3D (en cours)
Olivier Huet
Le #9722901
Bonjour,

yarocco a écrit :
Je voudrais recuperer la pile de mon programme.




En fait, es-tu sûr que Delphi génère des .pdb corrects ? Sur ce point,
je ne connais pas du tout delphi, alors je ne connais pas la réponse.


Est-ce que c'est dans le but de faire générer des bug report par tes
clients / utilisateurs ? Si oui, pourquoi ne pas plutôt faire générer
par ton programme des minidumps ( via la DbgHelp aussi, comme ton code,
sauf que c'est plus court :-) ), et te les faire envoyer par mail ?


Remarque que si la réponse à ma première question est non, tu auras du
mal à les exploiter, mais tu en aura tout autant à faire marcher ton
code :-)


Pour ton code en lui même, je ne connais quasiement pas Delphi : je ne
peux pas te dire ce qui peut clocher.


Pour des exemples de parcours de pile etc. avec DbgHelp depuis du code
(C++ de Visual C++ 2003 et éventuellement 6), et pour ce que tu semble
vouloir faire, je te conseille de lire "Debugging Applications for
Microsoft .Net and Microsoft Windows", de John Robbins


Bonne chance,
Olivier Huet
Olivier Huet
Le #9722891
Olivier Huet a écrit :

En fait, es-tu sûr que Delphi génère des .pdb corrects ? Sur ce point,
je ne connais pas du tout delphi, alors je ne connais pas la réponse.




oups, j'ai été un peu vite, disons soit des .pdb corrects soit des
symboles de debug dans une autre forme, lisible par DbgHelp (de
Microsoft) :-)

(remarquons que là non plus, je ne connais pas assez Delphi pour répondre)



je sais, il faut tourner 7 fois sa langue dans sa bouche avant de
prononcer un mot.

Olivier Huet
dark poulpo
Le #9722881
lol, javais pas vu que cetait du delphi!!!! jai survolé!!! :-p

--
-----
http://dark.freezee.org/
- Dark Update v1.0
- Dark Emule v0.44b r4
- Dark Desktop 3D (en cours)
dark poulpo
Le #9722871
je pense que tu devrais quand meme inclure de l'assembleur pour ta pile, vu
que cest possible en delphi.


--
-----
http://dark.freezee.org/
- Dark Update v1.0
- Dark Emule v0.44b r4
- Dark Desktop 3D (en cours)
Publicité
Suivre les réponses
Poster une réponse
Anonyme