根据需要装载/卸载ELF部分?

对于一个比较模糊的用例,我希望有一个(大的)静态链接的Linux可执行文件,由一小块控制代码和大量的静态(只读)数据组成。 有没有可能为了节省内存,让加载程序只加载控制代码的部分,然后手动加载需要的RO数据部分,并在处理完成后再次卸载它们?

这可能吗?

(我认为数据stream(在文件系统级别)可以用来解决这个问题,但是它们对我来说是不可用的(EXT3),因为数据stream很容易丢失,所以分发会很棘手。

Solutions Collecting From Web of "根据需要装载/卸载ELF部分?"

这(很可能)已经为你照顾。

当然,真正的答案是依赖于系统的,但是一般来说,现代操作系统(当然还有Linux)使用按需分页来执行可执行文件,所以没有RAM将被实际分配给ELF文件中没有引用的部分。

不要将你的blob链接到二进制文件,而是将它们附加到它。 他们不会被映射,但你可以阅读或映射他们,因为你需要他们。

有些答案有些误导,因为它们暗示整个二进制将被映射。 不,这是错的。 并非所有东西都会被映射!

证明:

$ cat /proc/self/maps **08048000**-08052000 r-xp 00000000 08:03 78433 /bin/cat **08052000**-08053000 rw-p 0000a000 08:03 78433 /bin/cat ... 

这是将被映射的唯一两个部分。 为什么? 因为这些是唯一具有DT_LOAD类型的:

 $ readelf -l /bin/cat Elf file type is EXEC (Executable file) Entry point 0x8049cf8 There are 8 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 RE 0x4 INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 **0x08048000** 0x08048000 0x09ba0 0x09ba0 RE 0x1000 << LOAD 0x00a000 **0x08052000** 0x08052000 0x00228 0x00804 RW 0x1000 << DYNAMIC 0x00a014 0x08052014 0x08052014 0x000c8 0x000c8 RW 0x4 NOTE 0x000148 0x08048148 0x08048148 0x00044 0x00044 R 0x4 GNU_EH_FRAME 0x008c48 0x08050c48 0x08050c48 0x002a4 0x002a4 R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 

您还会注意到虚拟地址与ELF文件中定义的相同。

在实践中,您只能访问该文件的前40个KiB(0x8052000-0x8048000 = 40960字节)。 这对于ELF头文件来说已经足够了,但是不能访问DWARF .debug头文件,更不用说字符串表(.strtab)了。

如果你想访问所有的ELF部分,最简单的就是映射整个文件。

不,如果它是ELF文件的一部分,它将被映射。 我不确定ELF的细节,但是如果这是一个PE文件,那么您可以简单地将添加的数据标记在PE文件的结尾,而不是PE结构中。 不属于PE结构的数据不会被映射到Windows中的内存。 我怀疑同样存在于ELF中。