首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从共享库导出符号

如何从共享库导出符号
EN

Stack Overflow用户
提问于 2009-04-16 13:40:57
回答 3查看 35.8K关注 0票数 5

我使用Windows编译器使用*.so对象代码文件(C源代码)创建了一个共享库( *.o )。

我将这个共享对象与一个应用程序(在Linux主机上使用gcc作为ARM目标)链接起来,并获得一个可执行文件,在运行时生成分段错误。(我知道我必须调试它!)

与创建共享库不同,如果我创建了一个具有相同源文件的静态库,然后链接到应用程序,然后执行应用程序,那么它可以正常工作。

所以我的问题是:

  1. 我是否需要使用某些构造在源文件中显式地导出符号(导出到应用程序的函数)或任何其他符号,以便在与应用程序链接时工作良好?什么是需要的,我该怎么做?
  2. 共享库是如何工作的?即,在创建库时,将在库中给出函数加载和运行的地址。应用程序( main() )如何解析要执行库函数的地址?
  3. 静态库是如何工作的,即在静态库的情况下,这个地址规范和解析是如何发生的?
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-04-16 14:32:49

这就是它在linux上的工作方式:

不,你什么都不用做。但是,可以使用gcc -fvisibility命令行参数限制导出变量,并使用可见性属性显式标记导出的条目。

2)可执行文件将包含它导入的所有函数(这些都是具有默认可见性的函数)。加载器/链接器将选择一个地址来加载库,并在运行之前填充该表,对这些函数的调用是间接调用。(注意,这也适用于共享对象)

3)静态链接是在链接时间(编译后)执行的。实际地址在程序集中被替换,它们是直接调用。

注意:有一个叫做PIC (位置独立代码)的东西。AFAIK,它处理对同一个共享对象中的数据/函数的引用,因此链接器在加载库时不需要覆盖库的一半代码,就像代码不对自己的数据进行任何绝对引用一样。你可以试着用它做实验。

票数 13
EN

Stack Overflow用户

发布于 2011-04-02 03:22:26

  1. 您不需要使用gcc导出符号,因为默认情况下它会导出所有符号;但是,RVDS可能会也可能不会这样做。检查您的RVDS编译器文档(尝试将其配置为“可重定位ELF”输出?)
  2. Linux上的共享库必须是可重定位的,因为基址是在运行时确定的。生成独立于位置的代码是理想的,因为它减少了重新定位库所需的工作量。如果您的库不可重定位,它将崩溃(换句话说,在创建动态库之前,不要从对象文件中删除重新定位信息)。在选择基址和重新定位内部引用之后,符号在运行时被解析为地址。
  3. 对于静态库,所有符号解析、重定位和负载地址的分配都发生在编译时。

我唯一的猜测是,您的编译器正在输出的代码在运行时是不可重定位的。这对我来说是个谜,但如果不打破静态库,怎么会发生呢?

如果要从RVDS直接生成静态库和共享库,可以选择尝试将静态库转换为共享库:

代码语言:javascript
复制
gcc -shared -o libfoo.so libfoo.a

如果这有帮助,那么RVDS的共享库链接器(或其配置)可能会被破坏。

票数 3
EN

Stack Overflow用户

发布于 2009-05-20 05:23:25

你知道坠机的原因吗?

如果要动态加载共享库(例如通过dlopen()),一种可能是假设库在未加载时加载OK,然后尝试通过空指针执行函数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/756174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档