如何从共享库导出符号

发布于 2024-07-16 22:37:47 字数 525 浏览 7 评论 0原文

我在 Windows 主机上使用 RVDS 编译器使用 *.o 目标代码文件(C 源代码)创建了一个共享库 (*.so)。

我将此共享对象与应用程序链接(对于 Linux 主机上的 ARM 目标使用 gcc)并获取可执行文件,该可执行文件在运行时会生成分段错误。 (我知道我必须调试它!)

如果我创建一个具有相同源文件的静态库,而不是创建共享库,然后与应用程序链接,然后执行应用程序,它会按预期正常工作。

所以我的问题是:

  1. 我是否需要使用某些构造在我的源文件中明确导出符号(导出到应用程序的函数)或任何其他符号,以便在与应用程序链接时它可以正常工作? 需要什么以及如何做到这一点?

  2. 共享库如何工作?即在创建库时会在库中给出加载和运行函数的地址。 应用程序( main() )如何解析要执行库函数的地址?

  3. 静态库如何工作,即在静态库的情况下如何进行地址指定和解析?

I created a shared library (*.so) using the *.o object code files (C source code) using RVDS compiler on Windows Host.

I link this shared object with a application (using gcc for ARM target on Linux host) and obtain a executable, which on running generates segmentation fault. (I know I have to debug it!)

Instead of creating shared library, if I create a static library with same source files, and then link with the application, and then execute the application it works fine as expected.

So my questions are:

  1. Do I need to export symbols(functions exported to application) or any other symbols, explicitly, in my source file using some constructs so that it works fine when linked with an application? What is needed and how do I do that?

  2. How does shared library work?, i.e. will the addresses where the functions will be loaded and run, will be given in the library be given when library is created. How does the application ( main() ) resolve the addresses where the library functions are to be executed?

  3. How does a static library work, i.e. how does this address specification and resolving happen in case of static library?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

江南烟雨〆相思醉 2024-07-23 22:37:47

这就是它在 Linux 上的工作原理:

1) 不,你不需要做任何事情。 但是,您可以使用 gcc -fvisibility 命令行参数限制导出变量,并使用 Visibility 属性显式标记导出的条目。

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

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

注意:有一种叫做PIC(位置无关代码)的东西。 AFAIK,这处理对同一共享对象中的数据/函数的引用,因此链接器在加载库时不需要覆盖库的一半代码,因为代码不会对其进行任何绝对引用自己的数据。 您可以尝试尝试一下。

This is how it works on linux:

1) No, you needn't do anything. You can, however, restrict exporting variables with gcc -fvisibility command line argument and explicitly flag exported entries with the visibility attribute.

2) The executable will have a table of all functions it imports (these are all functions with default visibility). The loader/linker will pick an address to load the libraries to and fill this table just before running, the calls to those functions are indirect calls. (Note that this holds for shared objects as well)

3) Static linking is performed on link-time (which is after you compile). The actual addresses are substituted in the assembly, and they are direct calls.

Note: There is the thing called PIC (position independent code). AFAIK, this deals with references to data/functions in the same shared object, so the linker needn't overwrite half of the code of the library when loading the library, in the way that the code doesn't make any absolute references to its own data. You might try to experiment with it.

遇到 2024-07-23 22:37:47
  1. 您不需要使用gcc导出符号,因为它默认导出所有符号; 然而,RVDS 可能会也可能不会做同样的事情。 检查您的 RVDS 编译器文档(尝试将其配置为 '可重定位 ELF' 输出?)

  2. Linux 上的共享库必须是可重定位的,因为基地址是在运行时确定的。 生成与位置无关的代码是理想的选择,因为它减少了重新定位库所需的工作量。 如果您的库不可重定位,它将会崩溃(换句话说,在创建动态库之前不要从对象文件中删除重定位信息)。 选择基地址并重定位内部引用后,符号将在运行时解析为地址。

  3. 对于静态库,所有符号解析、重定位和加载地址分配都在编译时发生。

    对于静态库,所有符号

我唯一的猜测是,不知何故,编译器发出的代码在运行时不可重定位。 不过,对我来说,在不破坏静态库的情况下如何发生这种情况是一个谜...

如果您直接从 RVDS 生成静态库和共享库,一种选择是尝试将该静态库转换为共享库:

gcc -shared -o libfoo.so libfoo.a

如果这有帮助,则 RVDS 的共享库链接器(或其配置)可能已损坏。

  1. You do not need to export symbols with gcc, as it exports all symbols by default; RVDS may or may not do the same, however. Check your RVDS compiler documentation (try configuring it for 'Relocatable ELF' output?)

  2. Shared libraries on Linux must be relocatable, as the base address is determined at runtime. Generating position-independent code is ideal, as it reduces the amount of work needed to relocate the library. If your library is not relocatable it will crash (in other words, don't strip relocation information from your object files before making the dynamic library). Symbols are resolved to addresses at runtime after the base address is selected and internal references are relocated.

  3. With static libraries, all symbol resolution, relocation, and assignment of load addresses happens at compile time.

My only guess would be that somehow, the code your compiler is putting out is not relocatable at runtime. It's a mystery to me how that would happen without breaking static libraries as well, though...

If you're generating a static library and shared library directly from RVDS, one option would be to try to convert that static library to a shared library:

gcc -shared -o libfoo.so libfoo.a

If this helps, then RVDS's shared library linker (or its configuration) is likely broken.

半世蒼涼 2024-07-23 22:37:47

您知道事故原因吗?

如果您动态加载共享库(例如通过 dlopen()),一种可能性是您假设库加载正常,但实际上没有加载,然后尝试通过空指针执行函数。

Do you know anything about the cause of the crash?

One possibility if you are loading the shared library dynamically (e.g. via dlopen()) is that you are assuming that the library loaded OK when it didn't, and then are trying to execute functions via null pointers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文