3

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

这可能吗?

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

4

4 回答 4

4

这(很可能)已经为您处理好了。

真正的答案当然取决于系统,但一般来说,现代操作系统(当然还有 Linux)对可执行文件使用按需分页,因此实际上不会为您不引用的 ELF 文件的部分分配 RAM。

于 2009-10-31T04:06:04.450 回答
1

不要将你的 blob 链接到二进制文件中,而是将它们附加到它上面。它们不会被映射,但您可以根据需要读取或映射它们。

于 2009-11-06T01:00:43.000 回答
1

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

证明:

$ 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 R E 0x4
  INTERP         0x000134 0x08048134 0x08048134 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 **0x08048000** 0x08048000 0x09ba0 0x09ba0 R E 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 部分,最简单的方法是映射整个文件。

于 2011-05-22T12:38:55.440 回答
0

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

于 2009-10-30T10:46:16.297 回答