商务合作:179001057@qq.com

编译器的一些参数

技术2022-05-11  0


某平台价值19860元的编程课程资料免费领取【点我领取】


    继续昨天的话题,用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)