Hi,
once again I would like to get your advice on spec files. I now compiled a Windows application successful against winelib and can link it without problems. However, the application segfaults immediately when starting wine. I am tracking this back to .spec files (although I will need to debug in the next free time to be sure), since they are the weakest link I am seeing, since I wrote most of them by hand. So it would be great if you can answer the following questions:
- Automatic generation: I composed the spec files by hand, based on Windows def files. Is there an automatic way to do that? I noticed a (somewhat hidden) tool called winedump, with nearly not existing documentation, but could not make much use of it. Any hints here?
- Stack size and parameters in spec file: The def files are, as far as I know, very similar to the spec files: they contain the function name (either mangled or not mangled), as well as (most of the time) the stack space - format: functionname@stackspace. Is there anything wrong to translate an entry for "char* testfunc(char* str, int var1, long var2, long* ptr)" called "testfunc@16" into "@stdcall testfunc(ptr ptr ptr ptr)", without caring for the type of parameters? More explicitely asked, what use do I have from using str or long instead of ptr in the spec file?
- Stdcall vs. cdecl How do I find out whether a function uses CDECL instead of STDCALL? I found the information (link lost unfortunately) that entries in the def file like testfunc1@0 are called via STDCALL, whereas in case of testfunc2 without any @ specifying the space is CDECL. Is this guess right? If not, how else do I find this out?
Thanks again for any help!
Cheers, Martin ______________________________________________________________________________ Bestes Testergebnis: Stiftung Warentest Doppelsieg fur WEB.DE FreeMail und WEB.DE Club. Nur fuer unsere Nutzer! http://f.web.de/?mc=021182
Martin Tröster wrote:
Hi,
- Stdcall vs. cdecl
How do I find out whether a function uses CDECL instead of STDCALL? I found the information (link lost unfortunately) that entries in the def file like testfunc1@0 are called via STDCALL, whereas in case of testfunc2 without any @ specifying the space is CDECL. Is this guess right? If not, how else do I find this out?
STDCALL means PASCAL call format. This means two things, mostly. First - it means arguments are pushed on the stack left to right instead of right to left (no way you can pass printf style variable length arguments). The second is that it is the functions' responsibility, rather than the caller, to remove the arguments from the stack.
With the C calling convention, if the caller places more arguments on the stack than the function expects, nothing bad will happen. The same caller (that presumably knows how much arguments there are on the stack) releases the stack. As the arguments are pushed right to left, the first argument is always in the same position in relation to the stack pointer when calling the function. This means that if the function expects three arguments, and the caller sends 4, noone will ever notice (assuming the first three are understood correctly, of course).
With the Pascal calling convention, such a case is disastrous. As the arguments are cleared by the called function, if it thinks there is a different number or arguments on the stack than there really is, the function will return to the caller with the stack pointer in the wrong place. The program is most likely to crash the moment any further stack activity takes place.
In order to avoid this problem, STDCALL functions mangle into the function's name a number indicating the number of bytes the arguments for the function take on the stack. This gives a certain assurance that a mismatch between caller and callee notion of what the arguments are will be translated into a linker failure, rather than inexplicable, seemingly random, runtime crashes.
Warning: the following paragraph is pure guesswork. The long explanation was just a way to say that your idea that symbols that have the form of "name@number" are STDCALL symbols, while symobls that are pure name are CDECL, seems the only way to understand things.
Thanks again for any help!
Cheers, Martin
Shachar
Shachar Shemesh wine-devel@shemesh.biz writes:
STDCALL means PASCAL call format. This means two things, mostly. First
it means arguments are pushed on the stack left to right instead of right to left (no way you can pass printf style variable length arguments). The second is that it is the functions' responsibility, rather than the caller, to remove the arguments from the stack.
Actually stdcall is not the same as pascal, it's a hybrid between pascal and C. With stdcall, arguments are pushed right to left like in C, but the called function cleans up the stack.
Martin Tröster wrote:
How do I find out whether a function uses CDECL instead of STDCALL? I found the information (link lost unfortunately) that entries in the def file like testfunc1@0 are called via STDCALL, whereas in case of testfunc2 without any @ specifying the space is CDECL. Is this guess right? If not, how else do I find this out?
The most safe one I have known is to disassemble it and look over the output. If the function have no parameters, you can declare it as either CDECL or STDCALL.
Suppose it have some parameters and its type is CDECL, you can find: 1. "lret" in the function 2. it will be called in a way like pushl something1 pushl something2 call address of testfunc1@0 addl $8, %%esp
and for a STDCALL, there are: 1. something that is similar to "lret $8" in the function 2. it will be called in a way like pushl something1 pushl something2 call address of testfunc1@0
Thanks again for any help!
Cheers, Martin
First - it appears the function name is sufficient to detect that. Despite that, here are a few nit-picking corrections:
Jerry Jenkins wrote:
Martin Tröster wrote:
How do I find out whether a function uses CDECL instead of STDCALL? I found the information (link lost unfortunately) that entries in the def file like testfunc1@0 are called via STDCALL, whereas in case of testfunc2 without any @ specifying the space is CDECL. Is this guess right? If not, how else do I find this out?
The most safe one I have known is to disassemble it and look over the output. If the function have no parameters, you can declare it as either CDECL or STDCALL.
Suppose it have some parameters and its type is CDECL, you can find:
- "lret" in the function
- it will be called in a way like
pushl something1 pushl something2 call address of testfunc1@0 addl $8, %%esp
Not necessarily, not by a long shot. The above is correct if the program was not optimized. Optimizations change EVERYTHING. It is very common to see the "addl" (that pops the arguments from the stack) agregated for several function calls (making it both of the wrong number, and not immediately after the return). The same goes for the "push" - they may be further up. In fact, I have seen cases where an argument was pushed for one function, and then used for another without pop and repush (I suppose this required deeper understanding of the function, as it was it's right to change it on stack).
In other words - you cannot teach assembly pattern recognition in three lines on a mailing list, I'm afraid.
While wer'e nitpicking - function name won't have the "@0".
and for a STDCALL, there are:
- something that is similar to "lret $8" in the function
- it will be called in a way like
pushl something1 pushl something2 call address of testfunc1@0
Same considerations go here. While nitpicking - in your case function will have "testfunc1@8", as we pushed two arguments.
"Martin Tröster" troymcclure@web.de writes:
- Stack size and parameters in spec file:
The def files are, as far as I know, very similar to the spec files: they contain the function name (either mangled or not mangled), as well as (most of the time) the stack space - format: functionname@stackspace. Is there anything wrong to translate an entry for "char* testfunc(char* str, int var1, long var2, long* ptr)" called "testfunc@16" into "@stdcall testfunc(ptr ptr ptr ptr)", without caring for the type of parameters? More explicitely asked, what use do I have from using str or long instead of ptr in the spec file?
All it does is allow you to get more readable output from the relay traces. If you don't care about that, using 'ptr' everywhere works just fine.
- Stdcall vs. cdecl
How do I find out whether a function uses CDECL instead of STDCALL? I found the information (link lost unfortunately) that entries in the def file like testfunc1@0 are called via STDCALL, whereas in case of testfunc2 without any @ specifying the space is CDECL. Is this guess right? If not, how else do I find this out?
Yes this is correct, the stdcall functions are the ones decorated with @xxx.