creating shared dlls yields undefined reference to `WinMain@16' in mingw 4.3

BGB cr88192@hotmail.com
Fri Dec 19 05:44:00 GMT 2008


----- Original Message ----- 
From: "Daniel Walter" <d2walter@hotmail.com>
To: "Andrew Haley" <aph@redhat.com>
Cc: "Danny Smith" <dansmister@gmail.com>; <java@gcc.gnu.org>
Sent: Friday, December 19, 2008 3:02 AM
Subject: Re: creating shared dlls yields undefined reference to `WinMain@16' 
in mingw 4.3
> GetProcAddress can be used to find the address of a function if it is 
> exported, though WinMain is generally not exported. Windows processes are 
> started with an entry point address that comes from the exe header, not 
> from a symbol. I tried searching an exe for WinMain with grep and then 
> looked for symbols with dumpbin and didn't find anything.
>> I am not sure how it helps to have an address for WinMain though. If I 
> understand things properly, this is being used to backtrace the stack for 
> exception information. Unless I am wrong and there is compatibility 
> between MS and GCC call stacks, this won't be able to trace back to 
> WinMain anyway.
>
many functions in the Win32 API, and GCC by default, use different calling 
conventions.
much of the Win32 API (including WinMain and callbacks) use STDCALL.
int WINAPI WinMain (
 HINSTANCE hInstance, HINSTANCE hPrevInstance,
 LPSTR lpCmdLine, int nCmdShow)
note the 'WINAPI', this is important.
WINAPI is a macro that usually expands to '__stdcall'.
however, by default GCC, and many other compilers, use cdecl.
in general, many things on windows use the stdcall calling convention, which 
differs from cdecl both in terms of how the stack is managed, and also how 
functions are names (stdcall uses a name mangling scheme, and so it is 
necessary to look for the mangled form of the name, not the raw symbol).
also, take note of another details:
nearly all symbols on Windows have an underscore prefix, but this is not the 
case on Linux.
so, the actual function name for WinMain will look more like this:
_WinMain @ 4
(spaces inserted to avoid OE stupidity...).
as for GetProcAddress, I think it is the case that, by default, it will only 
look up exported symbols.
however, using the 'Tool Help' functions, one can also look up non-exported 
functions as well.
here is a chunk of code from a project known as FoNC which illustrates the 
practice (MIT liscense I guess, the authors do such weirdness as putting 
bibliographies in source files, ...):
<--
#if defined(WIN32)
# include <tlhelp32.h>
struct dll
{
char *name;
dlhandle_t handle;
struct dll *next;
};
static struct dll *dlls= 0;
static int dlinitialised= 0;
static void dlinit(void);
dlhandle_t dlopen(const char *path, int mode)
{
dlhandle_t handle= 0;
if (!dlinitialised) dlinit();
{
unsigned int errormode= SetErrorMode(SEM_FAILCRITICALERRORS);
SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
handle= GetModuleHandle(path);
if ((!handle) && path) handle= LoadLibrary(path);
SetErrorMode(errormode);
}
if (handle)
{
struct dll *dll= (struct dll *)malloc(sizeof(struct dll));
dll->handle= handle;
dll->next= dlls;
dlls= dll;
}
return handle;
}
static void dlinit(void)
{
HANDLE snapshot;
dlinitialised= 1;
if ((HANDLE)-1 != (snapshot= CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 
getpid())))
{
MODULEENTRY32 me32;
me32.dwSize= sizeof(MODULEENTRY32);
if (Module32First(snapshot, &me32))
do
dlopen(me32.szModule, RTLD_NOW | RTLD_GLOBAL);
while (Module32Next(snapshot, &me32));
CloseHandle(snapshot);
}
}
void *dlsym(dlhandle_t handle, const char *symbol)
{
void *addr= 0;
struct dll *dll;
if (!dlinitialised) dlinit();
if (handle)
{
addr= GetProcAddress(handle, symbol);
dprintf("dlsym %p \"%s\" -> %p\n", handle, symbol, addr);
return addr;
}
if ((addr= GetProcAddress(GetModuleHandle(0), symbol)))
{
dprintf("dlsym <main> \"%s\" -> %p\n", symbol, addr);
return addr;
}
for (dll= dlls; dll; dll= dll->next)
if ((addr= GetProcAddress(dll->handle, symbol)))
{
dprintf("dlsym dll %p \"%s\" -> %p\n", dll->handle, symbol, addr);
return addr;
}
dprintf("dlsym 0 \"%s\" -> FAIL\n", symbol);
return 0;
}
int dlclose(dlhandle_t handle)
{
struct dll *dll, **dllp;
for (dllp= &dlls; (dll= *dllp); dllp= &dll->next)
if (dll->handle == handle)
{
*dllp= dll->next;
free(dll);
break;
}
FreeLibrary(handle);
return 0;
}
#endif
-->
but, alas, I have not tested any of this personally...
> Daniel
>> ----- Original Message ----- 
> From: "Andrew Haley" <aph@redhat.com>
> To: "Daniel Walter" <d2walter@hotmail.com>
> Cc: "Danny Smith" <dansmister@gmail.com>; <java@gcc.gnu.org>
> Sent: Thursday, December 18, 2008 5:16 AM
> Subject: Re: creating shared dlls yields undefined reference to 
> `WinMain@16' in mingw 4.3
>>>> Daniel Walter wrote:
>>> Thank you for all the help on this. For anyone who is searching the
>>> archives for MinGW gcj information, I will summarize.
>>>>>> 1. If you are trying to build a dll in MinGW, you may need to make a
>>> dummy WinMain function.
>>>> This is wrong, though. Surely someone knows if Windows has something
>> like dlsym().
>>>> Andrew.
>>>>


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /