EDIT: Just try with something like this:
__declspec(dllexport) int foo(int param)
{return param*param;}
and compile. It turns out that functions from CRT and kernel32 is still imported. I have found that these come from the runtime. The question is why this runtime is assumed to be needed? I have read something about relocations. Is it a clue?
I have created a dll that provides a Win32 GUI widget. If I look at the import table for the dll generated by mingw-gcc it looks like the following (functions marked with (*) is those I called myself):
The Import Tables (interpreted .idata section contents)
vma: Hint Time Forward DLL First
Table Stamp Chain Name Thunk
00006000 00006050 00000000 00000000 00006354 000060d4
DLL Name: KERNEL32.dll
vma: Hint/Ord Member-Name Bound-To
6158 207 DeleteCriticalSection
6170 236 EnterCriticalSection
6188 352 FreeLibrary
6196 510 GetLastError
61a6 529 GetModuleHandleA (x)
61ba 577 GetProcAddress
61cc 734 InitializeCriticalSection
61e8 814 LeaveCriticalSection
6200 817 LoadLibraryA
6210 1173 TlsGetValue
621e 1213 VirtualProtect
6230 1215 VirtualQuery
00006014 00006084 00000000 00000000 00006394 00006108
DLL Name: msvcrt.dll
vma: Hint/Ord Member-Name Bound-To
6240 52 __dllonexit
624e 182 _errno
6258 266 _iob
6260 538 _winmajor
626c 583 abort
6274 595 calloc
627e 610 fflush
6288 625 free (x)
6290 633 fwrite
629a 676 malloc (x)
62a4 682 memcpy (x)
62ae 748 vfprintf
00006028 000060b8 00000000 00000000 000063b8 0000613c
DLL Name: USER32.dll
vma: Hint/Ord Member-Name Bound-To
62ba 134 DefWindowProcA (x)
62cc 342 GetWindowLongA (x)
62de 405 LoadCursorA (x)
62ec 480 RegisterClassExA (x)
6300 508 SendMessageA (x)
6310 569 SetWindowLongA (x)
It seems that there are much to do before I actually can use the DLL. For example, I never used fwrite in my code, yet it shows up in the import table. This indicates that it is used in some initialization routine that the compiler adds when linking. Why? Shouldn’t the (x)-marked functions be enough?
C code runs startup code. For a primer on what that means, read for example the first link on Google about “C startup code”
In short: it sets up the heap, stack and initializes static variables, along with things like the “environment”, the memory for the parameters passed to the program, internal locale, etc… What exactly depends on the OS, compiler and respective versions.
The dependencies are indeed linked in because of startup code which initializes thread-local storage and whatnot. You can prevent this (at least partially) by adding
-nodefaultlibswhen you link with gcc, but beware:Dragons Ahead!