2010-07-14 8 views
0

J'essaie de faire un appel à une fonction DLL (via GetProcAddress etc) à partir de C, en utilisant le compilateur lcc. La fonction est appelée et tout se passe bien, mais il semble que le haut de la pile soit corrompu. J'ai essayé de jouer avec des conventions d'appel (__stdcall/__cdecl), mais cela n'a pas aidé.corruption de pile étrange en raison d'un appel dll

Malheureusement, je n'ai pas accès au code dll, et je dois utiliser le compilateur lcc.

Je trouve que cette simple astuce évite la corruption de la pile:

void foo(params) 
{ 
    int dummy; 
    dll_foo(params); 
} 

Ici dll_foo est le pointeur retourné par GetProcAddress et la pile est une sorte de protection par la variable factice. Ce n'est donc pas le pointeur de pile qui est corrompu, mais les données en haut de la pile. Cela fonctionne comme ça, mais j'aimerais savoir la raison de la corruption.

Des idées?

UPD: Comme demandé dans les commentaires, voici les types de fonction réelle:

typedef unsigned char (CALLBACK Tfr)(unsigned char); 
typedef void (CALLBACK Tfw)(unsigned char,unsigned char); 
typedef int (CALLBACK Tfs)(int); 
typedef void (CALLBACK Tfwf)(int*,int); 

Tout ce qu'ils montrent un comportement similaire.

Malheureusement, il n'est pas si simple d'attacher un débogueur, car le code est compilé et lancé par Matlab, en utilisant le compilateur LCC, et il n'y a pas de support de débogage. Probablement je devrai reproduire ce problème dans une configuration autonome, mais ce n'est pas si facile de le faire.

Répondre

2

Semble comme vous utilisez MSVC, Debug + Registres Windows + Regarder la valeur de ESP avant et après l'appel Si elle ne correspond pas, alors changez d'abord la convention d'appel dans la déclaration de pointeur de fonction (avez-vous fait cela correctement?) Si cela ne correspond toujours pas, alors c'est __stdcall et vous n'avez pas deviné les arguments que vous devez passer correctement

Ou la fonction pourrait simplement clober le cadre de la pile, ce n'est pas impossible. La publication de votre déclaration de pointeur de fonction qui montre les vrais arguments aiderait probablement à mieux le diagnostiquer.

+0

Je suis d'accord concernant la déclaration du pointeur de fonction. –

+0

Non, j'utilise lcc et je ne sais pas comment attacher un débogueur (le compilateur est appelé par Matlab en fait).Les fonctions sont définies comme suit: "typedef unsigned char (CALLBACK Type_foo) (caractère non signé); Type_foo * foo;", il y en a quelques-uns avec des arguments différents, mais tous affichent le même comportement. Qu'est-ce qui est pour ESP, si c'était faux alors je suppose que mon hack ne fonctionnerait pas ... –

+0

Eh bien, écrivez un petit programme de test afin que vous puissiez réellement déboguer cela. –

1

Il me semble que vous étiez sur la bonne voie en regardant la convention d'appel. La principale chose à faire est de s'assurer que l'appelant et l'appelé utilisent la même convention. Typiquement pour une DLL, vous voulez utiliser __stdcall pour les deux, mais si (comme vous le dites) vous n'avez aucun contrôle sur la DLL, alors vous devez modifier votre code pour correspondre à ce qu'il fait. Malheureusement, il est presque impossible de deviner ce que c'est - je suis sûr que lcc (comme la plupart des compilateurs C et C++) peut produire du code pour utiliser une variété de conventions. Si votre hack fonctionne en ajoutant un dword supplémentaire sur la pile, il semble que vous ayez actuellement une discordance lorsque l'appelant et l'appelé tentent d'effacer les arguments de la pile (par exemple, l'appelant utilisant __cdecl et le calle utilisant __stdcall

+0

J'ai essayé à la fois __cdecl et __stdcall, le résultat est le même. Quoi d'autre pourrais-je essayer? –

1

Vous pouvez essayer de "suivre" l'appel de dll_foo() i assembleur à l'aide d'un débogueur, pour vérifier exactement ce que la routine empile.

Questions connexes