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 bon...j'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
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
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
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
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
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
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.
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)
yarocco
yarocco wrote:
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 bon...j'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
Merci pour ton aide Dark mais ca ne m'avance pas trop :) J'ai oublie de dire ce que j'avais : 1 adresse puis que du 00000012 ! Si quelqu'un a deja eu ca...il peut m'en faire part :) J'ai corriger les 2-3 erreurs d'implementation que j'avais mais ca n'a pas avance sur mon but : avoir ma pile !
yarocco wrote:
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 bon...j'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
Merci pour ton aide Dark mais ca ne m'avance pas trop :)
J'ai oublie de dire ce que j'avais : 1 adresse puis que du 00000012 !
Si quelqu'un a deja eu ca...il peut m'en faire part :)
J'ai corriger les 2-3 erreurs d'implementation que j'avais mais ca n'a
pas avance sur mon but : avoir ma pile !
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 bon...j'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
Merci pour ton aide Dark mais ca ne m'avance pas trop :) J'ai oublie de dire ce que j'avais : 1 adresse puis que du 00000012 ! Si quelqu'un a deja eu ca...il peut m'en faire part :) J'ai corriger les 2-3 erreurs d'implementation que j'avais mais ca n'a pas avance sur mon but : avoir ma pile !
adebaene
yarocco wrote:
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...
Tu parles de CallStackDumper je suppose?
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.
Evidemment que ca ne passe pas! Tu es dans un thread auxiliaire, qui a arrêté le thread principal (celui qui a appelé DumpCallStack) pour pouvoir prendre une "photo" figée de sa pile.
//Petit PS: j'avais essaye de passer le pointeur de HandleThread
par
le Param, mais ca passe pas, //Savez vous pourquoi ??
Je connais pas Delphi, alors non...
//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 !
Normal si le thread principal n'est pas arrêté (voir ma remarque plus bas).
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;
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
Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel état est le thread principal au moment où tu fait la SuspendThread dessus (depuis le thread auxiliaire), donc ta call stack ne sert à rien!
//A moins que sauver la pile ne prenne plus d'une minute ?!
Comment ca une boucle infinie? La WaitForSingleObject n'est même pas dans une boucle!
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...
Tu parles de CallStackDumper je suppose?
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.
Evidemment que ca ne passe pas! Tu es dans un thread auxiliaire, qui a
arrêté le thread principal (celui qui a appelé DumpCallStack) pour
pouvoir prendre une "photo" figée de sa pile.
//Petit PS: j'avais essaye de passer le pointeur de HandleThread
par
le Param, mais ca passe pas,
//Savez vous pourquoi ??
Je connais pas Delphi, alors non...
//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 !
Normal si le thread principal n'est pas arrêté (voir ma remarque plus
bas).
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;
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
Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel état
est le thread principal au moment où tu fait la SuspendThread dessus
(depuis le thread auxiliaire), donc ta call stack ne sert à rien!
//A moins que sauver la pile ne prenne plus d'une minute ?!
Comment ca une boucle infinie? La WaitForSingleObject n'est même pas
dans une boucle!
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...
Tu parles de CallStackDumper je suppose?
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.
Evidemment que ca ne passe pas! Tu es dans un thread auxiliaire, qui a arrêté le thread principal (celui qui a appelé DumpCallStack) pour pouvoir prendre une "photo" figée de sa pile.
//Petit PS: j'avais essaye de passer le pointeur de HandleThread
par
le Param, mais ca passe pas, //Savez vous pourquoi ??
Je connais pas Delphi, alors non...
//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 !
Normal si le thread principal n'est pas arrêté (voir ma remarque plus bas).
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;
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
Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel état est le thread principal au moment où tu fait la SuspendThread dessus (depuis le thread auxiliaire), donc ta call stack ne sert à rien!
//A moins que sauver la pile ne prenne plus d'une minute ?!
Comment ca une boucle infinie? La WaitForSingleObject n'est même pas dans une boucle!
//WaitForSingleObject(HandleEvent, INFINITE); //Mis en
commentaire
car me fais faire une boucle infinie
Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel état est le thread principal au moment où tu fait la SuspendThread dessus (depuis le thread auxiliaire), donc ta call stack ne sert à rien!
//A moins que sauver la pile ne prenne plus d'une minute ?!
Comment ca une boucle infinie? La WaitForSingleObject n'est même pas dans une boucle!
Je veux dire qu'il attend indefiniment :)
Oui, c'est bien CallStackDumper
//WaitForSingleObject(HandleEvent, INFINITE); //Mis en
commentaire
car me fais faire une boucle infinie
Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel état
est le thread principal au moment où tu fait la SuspendThread dessus
(depuis le thread auxiliaire), donc ta call stack ne sert à rien!
//A moins que sauver la pile ne prenne plus d'une minute ?!
Comment ca une boucle infinie? La WaitForSingleObject n'est même pas
dans une boucle!
//WaitForSingleObject(HandleEvent, INFINITE); //Mis en
commentaire
car me fais faire une boucle infinie
Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel état est le thread principal au moment où tu fait la SuspendThread dessus (depuis le thread auxiliaire), donc ta call stack ne sert à rien!
//A moins que sauver la pile ne prenne plus d'une minute ?!
Comment ca une boucle infinie? La WaitForSingleObject n'est même pas dans une boucle!
Je veux dire qu'il attend indefiniment :)
adebaene
yarocco wrote:
Oui, c'est bien CallStackDumper
>> //WaitForSingleObject(HandleEvent, INFINITE); //Mis en > > commentaire > >>car me fais faire une boucle infinie > > Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel
état
> est le thread principal au moment où tu fait la SuspendThread
dessus
> (depuis le thread auxiliaire), donc ta call stack ne sert à rien! > > >> //A moins que sauver la pile ne prenne plus d'une minute ?! > > Comment ca une boucle infinie? La WaitForSingleObject n'est même
pas
> dans une boucle! >
Je veux dire qu'il attend indefiniment :)
Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel bloquant dedans!
Sinon, je ne connais pas Delphi, mais commenc ca se fait que tu puisses accéder à TForm1.HandleThread dans le code du thread : MonThr := Form1.HandleThread;
C'est quoi Form1 la dedans? MonThread est bien une variable d'instance de TForm1 non? A mon avis commence par vérifier la valeur de ce handle à cet endroit du code, ca me semble louche.
Au passage, je ne comprends pas comment tu peux passer ManewFonction comme paramètre à CreateThread vu que sa signature n'est pas la bonne, mais ne connaissant pas Delphi quelque chose m'échappe peut-être.
Arnaud
yarocco wrote:
Oui, c'est bien CallStackDumper
>> //WaitForSingleObject(HandleEvent, INFINITE); //Mis en
>
> commentaire
>
>>car me fais faire une boucle infinie
>
> Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel
état
> est le thread principal au moment où tu fait la SuspendThread
dessus
> (depuis le thread auxiliaire), donc ta call stack ne sert à rien!
>
>
>> //A moins que sauver la pile ne prenne plus d'une minute ?!
>
> Comment ca une boucle infinie? La WaitForSingleObject n'est même
pas
> dans une boucle!
>
Je veux dire qu'il attend indefiniment :)
Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel
bloquant dedans!
Sinon, je ne connais pas Delphi, mais commenc ca se fait que tu puisses
accéder à TForm1.HandleThread dans le code du thread :
MonThr := Form1.HandleThread;
C'est quoi Form1 la dedans? MonThread est bien une variable d'instance
de TForm1 non? A mon avis commence par vérifier la valeur de ce handle
à cet endroit du code, ca me semble louche.
Au passage, je ne comprends pas comment tu peux passer ManewFonction
comme paramètre à CreateThread vu que sa signature n'est pas la
bonne, mais ne connaissant pas Delphi quelque chose m'échappe
peut-être.
>> //WaitForSingleObject(HandleEvent, INFINITE); //Mis en > > commentaire > >>car me fais faire une boucle infinie > > Si tu ne fais pas leWaitForSingleObject, tu ne sait pas dans quel
état
> est le thread principal au moment où tu fait la SuspendThread
dessus
> (depuis le thread auxiliaire), donc ta call stack ne sert à rien! > > >> //A moins que sauver la pile ne prenne plus d'une minute ?! > > Comment ca une boucle infinie? La WaitForSingleObject n'est même
pas
> dans une boucle! >
Je veux dire qu'il attend indefiniment :)
Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel bloquant dedans!
Sinon, je ne connais pas Delphi, mais commenc ca se fait que tu puisses accéder à TForm1.HandleThread dans le code du thread : MonThr := Form1.HandleThread;
C'est quoi Form1 la dedans? MonThread est bien une variable d'instance de TForm1 non? A mon avis commence par vérifier la valeur de ce handle à cet endroit du code, ca me semble louche.
Au passage, je ne comprends pas comment tu peux passer ManewFonction comme paramètre à CreateThread vu que sa signature n'est pas la bonne, mais ne connaissant pas Delphi quelque chose m'échappe peut-être.
Arnaud
yarocco
> Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel bloquant dedans!
Le thread auxiliaire essaye (enfin j'espere :P) de recuperer la pile justement avec ManewFonction ...ou c'est moi qui comprend rien ?? Apres, ce que je ne comprend pas c'est qu'on demande d'attendre indefiniment avec le WaitForSingleObject...et c'est ce qu'il fait, j'aimerais bien qu'il reprenne la main moi :)
Sinon, je ne connais pas Delphi, mais commenc ca se fait que tu puisses accéder à TForm1.HandleThread dans le code du thread : MonThr := Form1.HandleThread;
C'est quoi Form1 la dedans? MonThread est bien une variable d'instance de TForm1 non? A mon avis commence par vérifier la valeur de ce handle à cet endroit du code, ca me semble louche.
Ben, HandleThread est une variable (de moi meme pour stocker le Handle du Thread dupliqué) de l'objet Form1. Et Form1 est une instance de la fiche Windows.
Au passage, je ne comprends pas comment tu peux passer ManewFonction comme paramètre à CreateThread vu que sa signature n'est pas la bonne, mais ne connaissant pas Delphi quelque chose m'échappe peut-être.
Arnaud
Ben, c'est peut etre la que le bas blesse... La C/C++ n'est pas mon langage de base et j'ai du traduire ton code (pas trop dur je pense car fait appel aux meme API) et aussi les headers de DbgHelp (c'est peut etre la que j'ai plante !)
Mais qu'est ce que tu entends par : pas la meme signature ?? Ca expliquerait pourquoi mon param de ManewFonction ne passe pas....
> Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel
bloquant dedans!
Le thread auxiliaire essaye (enfin j'espere :P) de recuperer la pile
justement avec ManewFonction ...ou c'est moi qui comprend rien ??
Apres, ce que je ne comprend pas c'est qu'on demande d'attendre
indefiniment avec le WaitForSingleObject...et c'est ce qu'il fait,
j'aimerais bien qu'il reprenne la main moi :)
Sinon, je ne connais pas Delphi, mais commenc ca se fait que tu puisses
accéder à TForm1.HandleThread dans le code du thread :
MonThr := Form1.HandleThread;
C'est quoi Form1 la dedans? MonThread est bien une variable d'instance
de TForm1 non? A mon avis commence par vérifier la valeur de ce handle
à cet endroit du code, ca me semble louche.
Ben, HandleThread est une variable (de moi meme pour stocker le Handle
du Thread dupliqué) de l'objet Form1. Et Form1 est une instance de la
fiche Windows.
Au passage, je ne comprends pas comment tu peux passer ManewFonction
comme paramètre à CreateThread vu que sa signature n'est pas la
bonne, mais ne connaissant pas Delphi quelque chose m'échappe
peut-être.
Arnaud
Ben, c'est peut etre la que le bas blesse...
La C/C++ n'est pas mon langage de base et j'ai du traduire ton code (pas
trop dur je pense car fait appel aux meme API) et aussi les headers de
DbgHelp (c'est peut etre la que j'ai plante !)
Mais qu'est ce que tu entends par : pas la meme signature ??
Ca expliquerait pourquoi mon param de ManewFonction ne passe pas....
> Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel bloquant dedans!
Le thread auxiliaire essaye (enfin j'espere :P) de recuperer la pile justement avec ManewFonction ...ou c'est moi qui comprend rien ?? Apres, ce que je ne comprend pas c'est qu'on demande d'attendre indefiniment avec le WaitForSingleObject...et c'est ce qu'il fait, j'aimerais bien qu'il reprenne la main moi :)
Sinon, je ne connais pas Delphi, mais commenc ca se fait que tu puisses accéder à TForm1.HandleThread dans le code du thread : MonThr := Form1.HandleThread;
C'est quoi Form1 la dedans? MonThread est bien une variable d'instance de TForm1 non? A mon avis commence par vérifier la valeur de ce handle à cet endroit du code, ca me semble louche.
Ben, HandleThread est une variable (de moi meme pour stocker le Handle du Thread dupliqué) de l'objet Form1. Et Form1 est une instance de la fiche Windows.
Au passage, je ne comprends pas comment tu peux passer ManewFonction comme paramètre à CreateThread vu que sa signature n'est pas la bonne, mais ne connaissant pas Delphi quelque chose m'échappe peut-être.
Arnaud
Ben, c'est peut etre la que le bas blesse... La C/C++ n'est pas mon langage de base et j'ai du traduire ton code (pas trop dur je pense car fait appel aux meme API) et aussi les headers de DbgHelp (c'est peut etre la que j'ai plante !)
Mais qu'est ce que tu entends par : pas la meme signature ?? Ca expliquerait pourquoi mon param de ManewFonction ne passe pas....