Wine中PE格式文件的加載(一):Wine初始化過程

首先了解下Wine初始化過程。

我們執行”wine WeChat.exe”命令,發生的過程是怎麼樣的?接下來從wine源碼一步步分析函數調用過程。

在loader/目錄下的源碼編譯,由main.c生成了“wine”Linux可執行文件;preloader.c生成了“pre-loader”Linux可執行文件。

假設在終端通過命令“wine  WeChat.exe”啓動微信;該過程涉及preloader,但是最終會執行到“wine”中的main函數。所以這裏從wine的main函數調用wine_init開始分析。

wine_init函數如下圖所示:

主要做了以下三件事:

1.     調用了mmap_init()函數,這個函數與預留地址空間相關。

2.     通過wine_dlopen()裝入由Wine提供的動態連接庫ntdll.dll。由於Wine特殊的系統結構,它不能使用微軟的ntdll.dll,而只能使用Wine自己的DLL,這樣的DLL稱爲“內置(built-in)”DLL。

3.     執行內置ntdll.dll中的函數__wine_process_init()。先通過wine_dlsym()取得這個函數的入口地址,然後通過指針init_func進行調用。之所以要以這樣的方式調用,是因爲這個函數在ntdll.dll中,而wine_dlopen()只是裝入了這個DLL、卻並未完成與此模塊的動態鏈接。

 

一般而言,Wine既可以安裝使用本身的“內置”動態庫,也可以安裝使用Windows上相應的“原裝(native)”動態庫。但是,其中有幾個動態庫是特殊的,因而只能使用Wine自己的版本,ntdll就是其一。實際上Windows上的ntdll.dll中根本不會有__wine_process_init()這麼個函數。Wine自己的“內置”DLL實際上就是Linux的.so模塊,是在Linux環境下由gcc產生的。GNU的C庫glibc中提供了一組用來處理.so模塊的函數,上面的wine_dlopen()和wine_dlsym()最終都是調用這些庫函數(例如dlopen()和dlsym())來完成操作。

說明:

linux提供了加載和處理動態鏈接庫的系統調用,dlopen以指定模式打開指定的動態連接庫文件,並返回一個句柄給調用進程,dlsym通過句柄和連接符名稱獲取函數名或者變量名。

__wine_process_init函數如下圖所示:

主要做了以下四件事情:

1.     thread_init函數的調用

2.     由load_builtin_dll("kernel32.dll")裝入Wine的另一個“內置”動態連接庫kernel32.dll。可見kernel32.dll也必須是個“built-in(內置)”DLL。

3.     由LdrGetProcedureAddress()從裝入的kernel32.dll映像中取得函數__wine_kernel_init()的入口。

執行kernel32.dll中的函數__wine_kernel_init()。
發佈了28 篇原創文章 · 獲贊 9 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章