Windows 仅按顺序从dll导出函数不隐藏函数名

Windows 仅按顺序从dll导出函数不隐藏函数名,windows,dll,export,ordinal,Windows,Dll,Export,Ordinal,在VisualStudio中,我只想按顺序从dll导出函数。在source中,我将函数定义为: int my_function() { return 101; } // without declspec(dllexport) 在.def文件中: LIBRARY MyDll EXPORTS my_function @ 1 NONAME // NONAME, export directory will not contain function name

在VisualStudio中,我只想按顺序从dll导出函数。在source中,我将函数定义为:

int my_function() { return 101; }     // without declspec(dllexport)
在.def文件中:

LIBRARY MyDll
    EXPORTS
        my_function @ 1 NONAME        // NONAME, export directory will not contain function name
在主程序中,我这样使用它:

#pragma comment(lib, "MyDll.lib")

declspec(dllimport) int my_function();

int main(int argc, char* argv[])
{
    int a = my_function();

    return 0;
}
代码编译和链接都很好<代码>非名称属性被记录为仅按顺序导出函数

MyDll的导出目录已将
NumberOfNames
设置为零,因此dll本身不包含名称信息。Exe文件按序号值导入函数,因此Exe也不包含名称信息


我尝试了不同的配置(调试、发布),但程序链接仍然很好。也许lib文件包含函数名和序数之间的某种映射?我读到lib文件包含函数thunks,所以我们可以在lib文件中有类似的内容:

my_function @ 1:
    jmp IAT[0]
my_another_function @ 2:
    jmp IAT[1]
在文件exe导入表中:

OriginalFirstThunk           FirstThunk
 0x80000001 (@ 1)          0x80000001 (@ 1)   // ordinal 1 will go through IAT[0]
 0x80000002 (@ 2)          0x80000002 (@ 2)   // ordinal 2 will go through IAT[1]
OriginalFirstThunk           FirstThunk
 0x80000001 (@ 1)             IAT[0]
 0x80000002 (@ 2)             IAT[1]
和内存中的exe导入表:

OriginalFirstThunk           FirstThunk
 0x80000001 (@ 1)          0x80000001 (@ 1)   // ordinal 1 will go through IAT[0]
 0x80000002 (@ 2)          0x80000002 (@ 2)   // ordinal 2 will go through IAT[1]
OriginalFirstThunk           FirstThunk
 0x80000001 (@ 1)             IAT[0]
 0x80000002 (@ 2)             IAT[1]
如果是这样,那么为了隐藏函数名,我们应该只提供dll文件,这意味着用户需要使用
LoadLibrary
加载dll,并使用
GetProcessAddress
?我在这里缺少什么?

来自MSDN:

如果要优化DLL的文件大小,请对每个导出的函数使用NONAME属性。使用NONAME属性,序号存储在DLL的导出表中,而不是函数名中。如果您要导出许多函数,这将是一个相当大的节省

换句话说,NONAME只影响DLL,而不影响导入库。因此,您正在观察的行为符合预期

从:

可选关键字PRIVATE可防止entryname包含在由链接生成的导入库中

因此,如果同时使用PRIVATE和NONAME,您应该会得到想要的结果。但是,这首先违背了提供导入库的目的,至少就特定函数而言是如此。如果您希望某些函数可以通过导入库访问,而某些函数只能通过GetProcAddress访问,那么它可能非常有用

您可能更愿意为最终用户可用于链接的功能提供别名,例如

LIBRARY MyDll
    EXPORTS
        function1=my_function @ 1 NONAME
        function2=my_other_function @ 2 NONAME
这应该将假名称“function1”和“function2”放入导入库中,以便最终用户可以使用这些名称链接到函数,同时仍然在导入库和DLL中隐藏秘密名称“my_function”和“my_other_function”。(我不明白为什么名字一开始就需要保密,但是YMMV。)

免责声明:我自己没有尝试过,此答案仅基于文档。

来自MSDN:

如果要优化DLL的文件大小,请对每个导出的函数使用NONAME属性。使用NONAME属性,序号存储在DLL的导出表中,而不是函数名中。如果您要导出许多函数,这将是一个相当大的节省

换句话说,NONAME只影响DLL,而不影响导入库。因此,您正在观察的行为符合预期

从:

可选关键字PRIVATE可防止entryname包含在由链接生成的导入库中

因此,如果同时使用PRIVATE和NONAME,您应该会得到想要的结果。但是,这首先违背了提供导入库的目的,至少就特定函数而言是如此。如果您希望某些函数可以通过导入库访问,而某些函数只能通过GetProcAddress访问,那么它可能非常有用

您可能更愿意为最终用户可用于链接的功能提供别名,例如

LIBRARY MyDll
    EXPORTS
        function1=my_function @ 1 NONAME
        function2=my_other_function @ 2 NONAME
这应该将假名称“function1”和“function2”放入导入库中,以便最终用户可以使用这些名称链接到函数,同时仍然在导入库和DLL中隐藏秘密名称“my_function”和“my_other_function”。(我不明白为什么名字一开始就需要保密,但是YMMV。)


免责声明:我自己没有尝试过,这个答案完全基于文档。

如果代码编译和链接很好,那么您的问题是什么?@selbie:我想知道为什么它链接很好,而它不应该。“我读到lib文件包含函数thunks”-这不是真的。在什么问题上?@RbMm:为什么我们仍然能够调用以其名称标记为NONAME的函数?如果代码编译并链接良好,那么您的问题是什么?@selbie:我想知道为什么它链接良好,而它不应该。“我读到lib文件包含函数thunks”-这不是真的。具体在什么问题上?@RbMm:为什么我们仍然能够调用名称为NONAME的函数?