如何创建静态链接共享库 [英] How to create static linked shared libraries

查看:218
本文介绍了如何创建静态链接共享库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关我的硕士论文我试图去适应一个ARM Cortex-M3的嵌入式系统的共享库的方法。由于我们有针对性的主板有没有MMU我认为,这将毫无意义用正常的动态共享库。由于的.text从闪存直接执行和。数据是在启动时复制到RAM我无法解决。数据相对于由此得到了太多的code。 GOT必须通过具有在链接时被定义的绝对地址来访问。那么,为什么不链接时分配给所有的符号固定的绝对地址...?

For my master's thesis i'm trying to adapt a shared library approach for an ARM Cortex-M3 embedded system. As our targeted board has no MMU I think that it would make no sense to use "normal" dynamic shared libraries. Because .text is executed directly from flash and .data is copied to RAM at boot time I can't address .data relative to the code thus GOT too. GOT would have to be accessed through an absolute address which has to be defined at link time. So why not assigning fixed absolute addresses to all symbols at link time...?

这本书链接器和加载我知道静态链接的共享库,即,其中在库的程序和数据地址被链接时势必可执行库。链接的章介绍了如何这样的库可在一般被创建并给予unix系统V,BSD / OS参考;上,同时提到Linux和它的uselib()系统调用。不幸的是,书中没有给出信息如何实际创建这样的库,如工具和/或编译器/链接器的开关。除了这本书,我几乎发现关于在野外这样的库的任何其他信息。我在这方面发现的唯一的事情是 $ P $砰砰的Linux版本。但截至上运行正常的动态连接库那算不上什么我在寻找。

From the book "Linkers and Loaders" I got aware of "static linked shared libraries, that is, libraries where program and data addresses in libraries are bound to executables at link time". The linked chapter describes how such libraries could be created in general and gives references to Unix System V, BSD/OS; but also mentions Linux and it's uselib() system call. Unfortunately the book gives no information how to actually create such libraries such as tools and/or compiler/linker switches. Apart from that book I hardly found any other information about such libraries "in the wild". The only thing I found in this regard was prelink for Linux. But as this operates on "normal" dynamic libraries thats not really what I'm searching for.

我担心的是,使用这类libaries的是非常具体的,所以没有共同存在的工具来创建它们。虽然在这方面所提到的uselib()系统调用使我想知道。但我想,以确保我还没有开始砍我自己的链接之前忽略的东西...;?)所以,任何人都可以给我关于这些库的详细信息。

I fear that the use of these kind of libaries is very specific, so that no common tools exists to create them. Although the mentioned uselib() syscall in this context makes me wondering. But I wanted to make sure that I haven't overlooked anything before starting to hack my own linker... ;) So could anyone give me more information about such libraries?

此外,我想知道是否有任何的gcc / LD开关,链接和重新定位一个文件,但保留在文件中的重定位项 - 因此,它可以重新搬迁呢?我发现了-r选项,但完全跳过搬迁过程。没有人有一个想法?

Furthermore I'm wondering if there is any gcc/ld switch which links and relocates a file but keeps the relocation entries in the file - so that it could be re-relocated? I found the "-r" option, but that completely skips the relocation process. Does anyone have an idea?

编辑:

是的,我也知道链接脚本。随着的gcc -o libfoo.c libfoo的-nostdlib -e initLib -Ttext 0xdeadc0de 我设法得到某种联系和放大器;搬迁对象文件。但到目前为止,我还没有发现任何可能性主程序反对这个链接,并把它作为共享库。 (链接动态共享库中的正常途径,将链接器被拒绝。)

Yes, I'm also aware of linker scripts. With gcc libfoo.c -o libfoo -nostdlib -e initLib -Ttext 0xdeadc0de I managed to get some sort of linked & relocated object file. But so far I haven't found any possibility to link a main program against this and use it as shared library. (The "normal way" of linking a dynamic shared library will be refused by the linker.)

推荐答案

等什么,也许什么。共享库的最小概念

Concepts

Minimum concept of what such a shared library maybe about.


  • 同样code

  • 不同的数据

有这个变化。你是否支持库之间的链接。是一个参考 DAG 结构或完全的循环?你要把code在ROM或支持code更新?你想一个的过程后加载库的初始运行?最后一个通常的静态共享库动态共享库的之间的差异。虽然很多人将禁止库之间的引用也是如此。

There are variations on this. Do you support linking between libraries. Are the references a DAG structure or fully cyclic? Do you want to put the code in ROM, or support code updates? Do you wish to load libraries after a process is initially run? The last one is generally the difference between static shared libraries and dynamic shared libraries. Although many people will forbid references between libraries as well.

最后,一切都将回落到处理器的寻址模式。在这种情况下,ARM的拇指。在装载的一般耦合到OS和所使用的二进制格式。您的工具链(编译器和链接)也必须支持二进制格式,可以生成所需的code。

Eventually, everything will come down to the addressing modes of the processor. In this case, the ARM thumb. The loader is generally coupled to the OS and the binary format in use. Your tool chain (compiler and linker) must also support the binary format and can generate the needed code.

有关通过寄存器访问数据的支持是内在的的 APCS (ARM的程序调用标准)。在这种情况下,数据是通过访问 SB (静态基地),这是注册 R9 。在静态基的和的堆栈检查的可选功能。我相信你可能需要配置/编译GCC启用或禁用这些选项。

Support for accessing data via a register is intrinsic in the APCS (the ARM Procedure calling standard). In this case, the data is accessed via the sb (for static base) which is register R9. The static base and stack checking are optional features. I believe you may need to configure/compile GCC to enable or disable these options.

选项 -msingle-PIC基 -mpic注册是的 GCC手册。这个想法是,一​​个操作系统最初将分配单独的数据为每个库用户,然后加载/重新加载 SB 上下文切换上。当code跑到图书馆,数据通过访问 SB 该实例的数据。

The options -msingle-pic-base and -mpic-register are in the GCC manual. The idea is that an OS will initially allocate separate data for each library user and then load/reload the sb on a context switch. When code runs to a library, the data is accessed via the sb for that instances data.

GCC的的 arm.c code require_pic_register()这的确code一代在一个共享库数据的引用。这可能对应 ARM ATPCS共享库力学。参见5.5节

Gcc's arm.c code has the require_pic_register() which does code generation for data references in a shared library. It may correspond to the ARM ATPCS shared library mechanics.See Sec 5.5

您可以通过使用宏和内联汇编和可能的功能说明,像的 部分 。然而,图书馆以及可能的过程中需要在这种情况下,code修改;也就是说,非标宏像 EXPORT(myFunction的)

You may circumvent the tool chain by using macros and inline assembler and possibly function annotations, like naked and section. However, the library and possibly the process need code modification in this case; Ie, non-standard macros like EXPORT(myFunction), etc.

如果系统完全指定(一个ROM映像),你可以让你可以pre-产生对于系统中的每个库中唯一的数据偏移的偏移量。这是通过一个链接脚本很容易做到。使用 NOLOAD ,并把库数据在一些假冒部分。它甚至可能使主程序的静态共享库的。举例来说,你正在网络设备有四个以太网端口。主要的应用程序处理一个端口上的流量。您可以生成不同的数据应用的四个实例来表示的端口被处理。

If the system is fully specified (a ROM image), you can make the offsets you can pre-generate data offsets that are unique for each library in the system. This is done fairly easily with a linker script. Use the NOLOAD and put the library data in some phony section. It is even possible to make the main program a static shared library. For instance, you are making a network device with four Ethernet ports. The main application handles traffic on one port. You can spawn four instances of the application with different data to indicate which port is being handled.

如果您有库类型的大型混合/匹配,脚打印为图书馆数据可能变大。在这种情况下,你需要重新调整 SB 时调用都是通过在外部API到库的包装函数的。

If you have a large mix/match of library types, the foot print for the library data may become large. In this case you need to re-adjust the sb when calls are made through a wrapper function on the external API to the library.

  void *__wrap_malloc(size_t size)  /* Wrapped version. */
  {
       /* Locals on stack */
       unsigned int new_sb = glob_libc; /* accessed via current sb. */
       void * rval;
       unsigned int old_sb;

       volatile asm(" mov %0, sb\n" : "=r" (old_sb);
       volatile asm(" mov sb, %0\n" :: "r" (new_sb);
       rval = __real_malloc(size);
       volatile asm(" mov sb, %0\n" :: "r" (old_sb);
       return rval;
  }

查看 GNU LD --wrap 选项。如果你有一个较大的同质组库需要这种复杂性。如果你的库只包含的libc / libsupc ++',那么你可能不需要任何包装

See the GNU ld --wrap option. This complexity is needed if you have a larger homogenous set of libraries. If your libraries consists of only 'libc/libsupc++', then you may not need to wrap anything.

有插入胶合板的 ARM ATPCS通过做相当的编译器,

The ARM ATPCS has veneers inserted by the compiler that do the equivalent,

LDR a4, [PC, #4] ; data address
MOV SB, a4
LDR a4, [PC, #4] ; function-entry
BX a4
DCD data-address
DCD function-entry

库数据使用这种技术的大小为4k(可能8k的,但是这可能需要编译器修改)。该限制是通过 LDR RN,[SB,#offset] ,被ARM限制偏移12位。使用包装,每个图书馆都有一个4K的限制。

The size of the library data using this technique is 4k (possibly 8k, but that might need compiler modification). The limit is via ldr rN, [sb, #offset], were ARM limits offset to 12bits. Using the wrapping, each library has a 4k limit.

如果您有不知道当原始应用程序版本,那么你需要用每个人,并通过OS加载器放置GOT类型的表在主应用程序的固定位置静态基地多个库。每个应用程序都需要空间,每个库的指针。如果库未使用的应用程序,然后操作系统并不需要分配的空间和指针可以是 NULL

If you have multiple libraries that are not known when the original application builds, then you need to wrap each one and place a GOT type table via the OS loader at a fixed location in the main applications static base. Each application will require space for a pointer for each library. If the library is not used by the application, then the OS does not need to allocate the space and that pointer can be NULL.

库表的可以通过已知位置在的.text 访问,可以通过原有的流程 SB 或经由堆栈的掩模。例如,如果所有的进程得到一个2K栈,则可以保留下16个字为一个库表。 SP&放大器; 〜0x7ff 会给所有任务的一个隐含的锚。操作系统需要分配任务堆栈以及

The library table can be accessed via known locations in .text, via the original processes sb or via a mask of the stack. For instance, if all processes get a 2K stack, you can reserve the lower 16 words for a library table. sp & ~0x7ff will give an implicit anchor for all tasks. The OS will need to allocate task stacks as well.

请注意,这个机制比ATPCS,它使用 SB 作为一个表来获得补偿实际库数据不同。由于内存是相当有限的Cortex-M3形容这是不可能的,每个图书馆都需要使用超过4K的数据。如果系统支持一个分配器,这是一个工作,围绕这个限制。

Note, this mechanism is different than the ATPCS, which uses sb as a table to get offsets to the actual library data. As the memory is rather limited for the Cortex-M3 described it is unlikely that each individual library will need to use more than 4k of data. If the system supports an allocator this is a work around to this limitation.

参考

  • Xflat technical overview - Technical discussion from the Xflat authors; Xflat is a uCLinux binary format that supports shared libraries. A very good read.
  • Linkage table and GOT - SO on PLT and GOT.
  • ARM EABI - The normal ARM binary format.
  • Assemblers and Loader, by David Solomon. Especially, pg262 A.3 Base Registers
  • ARM ATPCS, especially Section 5.5, Shared Libraries, pg18.
  • bFLT is another uCLinux binary format that supports shared libraries.

这篇关于如何创建静态链接共享库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆