This is the mail archive of the
mailing list for the Cygwin project.
RE: resolving _glGetString@4 by linking to _glGetString
- From: Jay K <jay dot krell at cornell dot edu>
- To: cygwin <cygwin at cygwin dot com>, <sisyphus1 at optusnet dot com dot au>
- Date: Mon, 12 Jul 2010 06:59:45 +0000
- Subject: RE: resolving _glGetString@4 by linking to _glGetString
- References: <firstname.lastname@example.org>
? > Not so much of an issue any more (still a bit curious about it, but). I soon
? > found that providing a '-lopengl32' link instead of
? > '/cygdrive/c/Windows/System32/opengl32.dll' fixed the problem.
Linking to /cygdrive/c/windows/system32/whatever is "never" right.
It is not easy to explain this though.
In the "Unix model", the "headers and libraries" come with the operating system.
? /usr/include, /lib, /usr/lib, etc.
In the "Windows model", they come separately with the compiler or a "development kit".
The "Unix model" advantages:
?? system is "self describing"
?? smaller: no separate "import libraries", just the dynamic libraries
The "Windows model" advantages:
? Sort of more amenable to cross builds. Including targeting an older or newer OS release.
I say "sort of" because, like, adding additional headers and libraries doesn't change the model.
In the "Unix model", any headers/libraries apart from "the OS" are sort of following a different model,
where in the "Windows model", they are all following the same model.
This isn't the "Unix" or "Windows" model really, it is just how things tend to be done on those systems.
If you look at Mac OS X development systems, they are closer to Windows.
If you have ever used "sysroot" with gcc, well, that is like Windows then.
Personally I prefer the Windows model.
And Cygwin follows it, because, well, again, the main difference is if the operating system
contains the headers/libraries needed. Cygwin can be as Gnuy/Linuxy/Posixy as it wants, but
the operating system doesn't contain the files it needs, so it includes them.
Now, there is something funny to this term "libraries".
You know, modern systems are heavily dynamically linked, and the information needed
by the dynamic linker and the "static linker" is similar/same, in particular for the "static linker"
to build an executable or library that references symbols dynamically.
The main information is just a list of function names.
?Sometimes what library contains what function, depending on the system and compiler/linker flags.
Thus it becomes reasonable seeming to point at the "running code" for libraries, instead
of some separate libraries, sometimes called "stub libraries" or "import libraries", etc.
?(These "import libraries" basically just contain lists of function names, no actual code;
? older forms of them do contain a jmp per function, but that hardly counts.)
Now, then, what is the difference between the file -lopengl32 found, vs. /cygdrive/c/windows/system32/opengl32.dll?
Well, Windows on x86 does have something uniquely slightly bad about it: There are multiple calling conventions.
And the different calling conventions lead to a form of "name mangling", even in C code.
There are generally three calling conventions.
Though some compilers let you declare custom ones, e.g. I believe gcc and OpenWatcom.
As well the compiler can create custom calling conventions for "static" functions. That is a different more general point and
? true on many systems.
Anyway, the three usual Windows/x86 calling conventions are "stdcall", "cdecl", "fastcall".
"cdecl" is usually the default.
Parameters passed on the stack, right to left, callER pops, function "Foo" is "mangled" to "_Foo".
"stdcall" is heavily used.
Parameters passed on the stack, right to left, callEE pops, function "Foo" is "mangled" to "_Foo@N"
where "N" is the decimal number of bytes of parameters, e.g. 0, 4, 8, 16, etc.
"fastcall" I don't know entirely, but roughly speaking, it passes the first 8 bytes of parameters in ecx, edx,
right to left, the rest on the stack, callEE pops, "Foo" becomes "_@Foo@N".
"cdecl" is "needed" for varargs i.e. printf, because caller pops.
"stdcall" is smaller/faster because callee pops.
Now, I said "stdcall" is heavily used.
Almost all public Windows functions (aka APIs) are stdcall.
So instead of generating a reference to " _glGetString", the compiler generates a reference to " _glGetString@4".
However presumably because it looks nicer or maybe for consistency with the other architectures, the exported
names are not "mangled" (or "decorated").
("other architectures": NT on MIPS, Alpha, PowerPC, IA64, AMD64, only one calling convention each)
If you run link -dump -exports %windir%\system32\opengl32.dll, you'll see plain "glGetString".
?There is no clear indication in the .dll that glGetString takes 4 bytes of parameters (maybe if you disassemble it...)
The file -lopengl32 found though, contains some stuff in it with both strings "_glGetString@4" and "glGetString".
The first is what symbol the linker should resolve against, the second is what it should stuck in the special data in the
file it is outputing.
(To repeat, I think distributing headers/libraries separate is good, but having multiple calling conventions is clearly mixed/bad.)
Problem reports: http://cygwin.com/problems.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple