d导出的讨论

原文
以下是导出的所有问题的列表:32位和64位问题:
1)导出全局变量会产生链接器错误
2)导出线本变量应该是错误(至少在C++中是这样)(.1)
3)应在模块有导出符号后立即导出模块信息.
4)不导出类的__gshared成员
5),未导出TestClassTypeInfo对象
6),未导出TestStructTypeInfo对象

请见随附复制案例.如果此重现案例实际编译并运行dll.应可支持共享运行时.

也应该导出导出符号引用的如ModuleInfos,TypeInfos,opEquals编译器生成符号.
.1不,至少ELF支持链接/访问另一个共享库的TLS值.
TLS访问,窗口还使用每个DLL索引,因此应该可链接/重定位它们.
问题似乎是导出使用类似C的规则来区分声明和定义.对声明,导出表明__declspec(dllimport),对定义,导出表明__declspec(dllexport).

export void foo();   // 当作导入
export void foo() {} // 当作导出

导出全局变量,需要初化器.

export __gshared int bar;     //当作导入
export __gshared int bar = 0; //当作导出

该规则没有意义,因为它是定义变量并默认初化.
要标记仅声明,应用外(extern).
此外,此行为总是需要包含导入模块声明的头文件.

1)导出全局变量会使链接器错误,由#10059漏洞修复.
2问题,不能链接到包含线本变量定义的DLL吗?
3问题,符号,对我,很有意义.

如果导出用户定义类型,则也应导出所有编译器生成的元数据,vtables,TypeInfo,RTInfo!Type等.
如果导出UDT,并不肯定导出是否表明导出所有成员.
要在druntime/phobos中添加导出注解,需要修复922错误.

变量?抱歉,不确定是否可使线本变量跨dll边界工作,所以应先让它成为错误,以后再允许它.

一些随机评论:
0,对静态和动态链接,想用相同代码时,不可用"导出".建议根据编译开关模块粒度导出每个公共符号.
1,但是,不能简单判断是从静态库还是动态库导入模块中的符号.但该区别是必要的,因为两种情况下,代码不同.也许模块级版本指示可控制它.
2,可用其他DLL中的TLS变量,但当前工具链可能不行.需要导出的是TLS节中符号偏移,及导出符号DLL_tls_index变量地址.然后如下读取变量:

mov EAX,[_imp_variable.tls_index]; 
//读导入表中`tls_index`的地址
mov EAX,[EAX]; //读`DLL`的`tls_index`
mov EBX,FS:[2C]; // tls_array
mov EBX,[EBX+4*EAX]; // `dll`的tls_start
mov ECX,[_imp_variable.offset];
//读`DLL`的`TLS`中变量的偏移
mov EDX,[EBX+ECX];//读变量

如果不可导出偏移,则DLL也需要_tls_start.
对每个只返回变量值地址的TLS变量,实现getter函数,不是更容易吗?

你是对的,函数会更简单.由于间接跳转,效率可能稍低,但避免了通过导入表的两次间接访问数据.
没有混淆保护和导出.如,可拆分为两个DLL,此时,可能需要导出/导入,私和包保护符号.

通过静态库,访问链接变量时,编译器会生成直接访问.但是,如果通过动态库链接,则编译器会通过导入表通过直接引用_imp_符号而不是原始符号来,生成另一级间接.也即,编译器必须知道符号是从动态库还是静态库中导入.

dll中的故事,注意自动链接

访问数据时,添加了些额外重定位数据来实现类似"自动导入".启动程序时,修复重定位,导入表地址.
可惜,这不适合64位应用,因为dmd生成的二进制文件中的重定位仅与32PC相关.不能在另一个DLL,传地址给变量,因为它可能在32位到不了的64位地址空间.

仅指的是"公共符号"?对我一切正常,但因为禁止从另一个模块访问,对私有符号,不重要.
也许我对窗口机制理解错了,但导出符号可以相同.类似ELFPLT,在导入库中绑定运行时.引用导入符号的代码,最后,静态链接到导入库.
函数符号,是的,这是正确的,但如前所述,要特殊处理数据符号.
好吧,问题是,是否可用"导出"来注解符号,并仍然创建静态库.

优化很好,但Walter表示他更喜欢经典(另一级间接)方式.总结:
0,导出何时表示DLL导入,何时表示DLL导出.讨论提出,可用命令行开关,对每个模块(包括子模块)启用dllimport/dllexport.
1,是否想要导出所有公开符号(C++正摆脱它,也许也应这样)
2,是否可导出整个类/构吗?如按导出标记,导出其vtable,类型信息,所有保护/公开函数,静态成员等.
3,需要导出模块哪些信息?一旦模块,有单个导出函数/类/变量,就会自动导出吗?

目前:没有标记.但是,应该创建方法,除非用编译器的命令行开关指定,"导出"应是无操作.

当前实现有些问题:

export void foo() {} // 声明=> dllexport
export void foo();   // 定义=> dllimport
export int a = 0;    // 定义=> dllexport
export int a;        // 声明=> dllimport 
 //因为它实际上是个定义,失败
export extern int a; // 声明=> dllimport

如果能避免额外的.di标头,那就太好了.

Unix上进入另一个方向.
此处有关推导更多信息.链接,
是的,因为无法注解编译器生成数据.
再次请避免滥用导出保护,因为会对未来语言扩展带来太多问题如:维护ABI兼容的私有符号,多个文件/对象中的模块定义,部分类.链接符号保护是根本不同的概念,应该提供正交控制.
是的,它是隐藏的编译器数据,可能需要链接ModuleInfo及其他符号.

在既创建,导出符号,又从另一个DLL导入符号的DLL中,这不管用.别名导出.
总结别名建议.
0,对每个导出的函数定义,还产生_imp_funcname别名符号.
1,对每个导出的数据定义,产生弱链接T*_imp_var=&var只读指针.
2,每当调用或访问导出符号时,使用_imp_*符号完成操作.
3,此类代码与导入库链接时,同DLL正确工作.
4,代码静态库链接时,引用正确的定义.
5,简单导出属性,可满足所有用例,不用担心dllimport/dllexport/无操作.
6,如果可用整个程序优化,则链接器可在静态链接时,优化额外间接寻址访问数据.
最后一点不重要,因为导出数据很少,且不好.
此外,这仅适合不应成为性能热点的API边界.
ELF导出,只需使符号可见,否则默认隐藏符号.
Mach-O的想法?和ELF一样?

你想用"导出"注解所有火卫一druntime来构建共享版本吗?已在注解地狱中,有nothrow,纯,@safe

是的,这就是意图.手动这样很重要,因为导出符号,表明致力于ABI稳定性,这应该是长期目标.

由于导出符号是的已知入口,有了是否更多推导非导出符号问题.
dmd很可能不能用微软链接器的LTO.

此外,这不仅会影响API的边界,还会影响访问全局数据:__gshared,共享变量和所有编译器内置全局数据符号,如模块信息,类型信息,vtables等.
这是因为,在不知道从DLL导入哪些符号时,就必须对这些符号添加间接寻址.如果决定用别名,必须对全局数据访问加上额外间接级.
完全同意.为了方便,要提供-exportall开关.

它会起作用.因为编译器命令行开关会指定模块名,所以不会转换所有导出dllexport.如,如果构建火卫一,会在命令行加上"-export std".这会把std模块中导出转换为dllexport.

因此,对同时导出和导入符号DLL非常有效.对dllimport,需要指定链接到共享的phobos库时,命令行有的等效的,如"-import std"开关.然后可添加到默认的sc.ini,这样用户就不必手动指定.

不!仅适合标记为导出的数据.所以很清楚可导入什么.
导出的UDT(vtable,rtti)的元数据和带导出成员模块的模块信息.注意,由于窗口不支持插入符号,因此直接从模块访问数据是安全的.

拥有源码,但不想改时,编译器开关有意义.
提供-export=public,package,private可能有意义,因为没人维护ABI.

不是vtables,因为它们已通过类实例间接寻址.

posted @   zjh6  阅读(13)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示