编译器的一些参数

    技术2022-05-11  11

        继续昨天的话题,用WDK6001编译驱动用了这么一些关键选项:

    (CL.exe)

    /Zl:省略 .obj 文件中的默认 C 运行时库名称。默认情况下,编译器将库名放入 .obj 文件中,以便使链接器指向正确的库。

    /Oi:生成内部函数,前一篇文章已经讲过了,(Cheack模式有,Free模式却没有)

     

    (Link.exe)

    /NODEFAULTLIB  在解析外部引用时忽略所有(或指定的)默认库

    /RELEASE 选项在 .exe 文件头中设置校验和。

    操作系统要求设备驱动程序的校验和。为设备驱动程序的发布版本设置校验和,以确保与未来的操作系统兼容。

    当指定 /SUBSYSTEM:NATIVE 选项时,默认情况下设置 /RELEASE 选项。

    /entry:GsDriverEntry@8 指定入口点

    /subsystem:native,6.00

     

    从上面看出C运行时库是肯定无法连接了,甚至用#pragma comment( lib, "" )也不行了,因为会被/NODEFAULTLIB忽略,可以看一下啊MSDN上的说明:

    lib Places a library-search record in the object file. This comment type must be accompanied by a commentstring parameter containing the name (and possibly the path) of the library that you want the linker to search. The library name follows the default library-search records in the object file; the linker searches for this library just as if you had named it on the command line provided that the library is not specified with /nodefaultlib. You can place multiple library-search records in the same source file; each record appears in the object file in the same order in which it is encountered in the source file.

     

    解决的办法是有的,可以在source里改:TARGETLIBS= $(DDK_LIB_PATH)/your.lib

    linker

    Places a linker option in the object file. You can use this comment-type to specify a linker option instead of passing it to the command line or specifying it in the development environment. For example, you can specify the /include option to force the inclusion of a symbol:

    #pragma comment(linker, "/include:__mySymbol") Only the following ( comment-type ) linker options are available to be passed to the linker identifier:

    /DEFAULTLIB

    /EXPORT

    /INCLUDE

    /MANIFESTDEPENDENCY

    /MERGE

    /SECTION

    /DEFAULTLIB 选项将一个 library 添加到 LINK 在解析引用时搜索的库列表。用 /DEFAULTLIB 指定的库在命令行上指定的库之后和 .obj 文件中指定的默认库之前被搜索。

    忽略所有默认库 (/NODEFAULTLIB) 选项重写 /DEFAULTLIB:library 。如果在两者中指定了相同的 library 名称,忽略库 (/NODEFAULTLIB:library ) 选项将重写 /DEFAULTLIB:library 。

     

    现在的编译器似乎跟vc的有很多区别了,,有些是还很智能,如果它发现某些函数是显而易见的结果甚至不编译函数了(直接给结果),真是神奇啊…………

     

    再说说程序入口点:

    /ENTRY 选项指定一个入口点函数作为 .exe 文件或 DLL 的起始地址。

    必须用 __stdcall 调用约定来定义函数。必须按 WinMain (对于 .exe 文件)或 DllEntryPoint (对于 DLL)的 Win32 API 中记录的内容定义参数和返回值。建议让链接器设置入口点,以便 C 运行时库正确初始化,并执行静态对象的 C++ 构造函数。

    默认情况下,起始地址为 C 运行时库中的函数名。链接器根据程序的属性来选择该函数,如下表所示。

    函数名

    ...的默认值

    mainCRTStartup (或 wmainCRTStartup )

    使用 /SUBSYSTEM:CONSOLE 的应用程序;调用 main (或 wmain )

    WinMainCRTStartup (或 wWinMainCRTStartup )

    使用 /SUBSYSTEM:WINDOWS 的应用程序;调用 WinMain (或 wWinMain ),它必须用 __stdcall 来定义

    _DllMainCRTStartup

    DLL;调用 DllMain (如果存在),DllMain 必须用 __stdcall 来定义

    如果未指定 /DLL 或 /SUBSYSTEM 选项,则链接器将根据是否定义了 main 或 WinMain 来选择子系统和入口点。

    函数 main 、WinMain 和 DllMain 是三种用户定义的入口点形式。

     

    上面说的非常清楚了,但是驱动程序并不连接C库函数,没有什么main。但/entry:GsDriverEntry@8我知道,关键是GsDriverEntry在哪里?哈哈,在这里WINDDK/6001~1.180/lib/wlh/i386/BufferOverflowK.lib,这个函数非常简单:

    NTSTATUS GsDriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegPath) {     LARGE_INTEGER tickCount;     KeQueryTickCount(&tickCount);     if(!___security_cookie || ___security_cookie == 0xbb40)     {         ULONG temp = (ULONG)&___security_cookie;         temp = ((temp >> 8) ^ tickCount.u.LowPart) & 0xffff;         if(temp)           ___security_cookie = temp;         else           ___security_cookie = tickCount.u.LowPart & 0xffff;     }     ___security_cookie_complement = ~___security_cookie;     return DriverEntry(DriverObject,RegPath); }

     

    哦!这里还有一个很大的问题:

    "/Oi:生成内部函数(Cheack模式有,Free模式却没有)"那Free模式怎么办!!!!!!!!

    我看到Free模式时有 /Oxs(完全优化)

    看看/Oxs的说明:

    /Ox 可与 /Os (/Oxs ) 结合使用以利于生成较小的代码大小(优化大小)。

    通常,/O2 应该优先于 /Ox ,而 /O1 优先于 /Oxs 。

    使用 /Ox 的作用与使用下列选项的作用相同:

    /Ob n ,其中 n = 2

    /Og(全局优化)

    /Oi(生成内部函数)

    /Os、/Ot(代码大小优先、代码速度优先)

    /Oy(框架指针省略)

    晕!又有/Oi,,用IDA看看它们的代码,有惊人的差别……


    最新回复(0)