2015 01 01 21 45 [c] 用 minGW 編譯較小的 dll 檔

因為前面有用minGW編譯最小的exe檔,
想說來試試看編譯一個較小的dll檔. (不用 msvcrt.dll)
其實跟 exe 檔其實沒太大改變,

最大區別是exe檔是用 __main,
而dll檔則是要改用DllMainCRTStartup.

剩下就不要去call到c library的function,
除了kernel32.dll以外,就不需要import其他的dll檔了.

dll.c 程式碼如下:

#include <windows.h>

#define EXPORT __declspec(dllexport)

BOOL WINAPI DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // Code to run when the DLL is loaded
            WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),"Load working...\n",16, NULL,NULL);
            break;

        case DLL_PROCESS_DETACH:
            // Code to run when the DLL is freed
            WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),"Unload working...\n",18, NULL,NULL);
            break;

        case DLL_THREAD_ATTACH:
            // Code to run when a thread is created during the DLL's lifetime
            break;

        case DLL_THREAD_DETACH:
            // Code to run when a thread ends normally.
            break;
    }
    return TRUE;
}

EXPORT void hello(void)
{
    WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),"Hello\n",6, NULL,NULL);
}

然後用minGW gcc去編譯,gcc -s -shared  -fno-asynchronous-unwind-tables -nostartfiles -nodefaultlibs dll.c -o test.dll -lkernel32 \
-Wl,--out-implib,libtest.a -Wl,--enable-auto-image-base -Wl,--dynamicbase

#-Wl,--entry=DllMainCRTStartup
而--entry則是可以用來更換dll的entry function,不過在gcc 64bit上怪怪地,
因為我並沒需要更改這個function name,所以就不需要用了.

測試程式source code如下:
#include <windows.h>
#include <stdio.h>
void hello();
int main () {
    /*Call the hello function*/
    hello();
    return 0;
}
用 gcc -o test.exe test.c -ltest -L.
$ ./test.exe
Load working...
Hello
Unload working...

剩下的可以用objdump觀察一下編譯出來的結果:
$ objdump -x test.dll
......
There is an import table in .idata at 0x6bec4000

The Import Tables (interpreted .idata section contents)
 vma:            Hint    Time      Forward  DLL       First
                 Table   Stamp     Chain    Name      Thunk
 00004000       00004028 00000000 00000000 00004064 00004034

        DLL Name: kernel32.dll
        vma:  Hint/Ord Member-Name Bound-To
        4040      608  GetStdHandle
        4050     1267  WriteFile

 00004014       00000000 00000000 00000000 00000000 00000000

There is an export table in .edata at 0x6bec3000

The Export Tables (interpreted .edata section contents)

Export Flags                    0
Time/Date stamp                 54a555b2
Major/Minor                     0/0
Name                            00003032 test.dll
Ordinal Base                    1
Number in:
        Export Address Table            00000001
        [Name Pointer/Ordinal] Table    00000001
Table Addresses
        Export Address Table            00003028
        Name Pointer Table              0000302c
        Ordinal Table                   00003030

Export Address Table -- Ordinal Base 1
        [   0] +base[   1] 109f Export RVA

[Ordinal/Name Pointer] Table
        [   0] hello
.....

看起來完全沒問題, 就這樣了...^__^