按需加载/卸载 ELF 部分?

发布于 2024-08-10 01:11:16 字数 216 浏览 2 评论 0原文

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

这可能吗?

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

For a rather obscure use case I'd like to have a (large) statically linked Linux executable made up of a small piece of control code and large pieces of static (read-only) data. Is it possible, to save memory, to get the loader to load only the sections for the control code, and then manually load the sections of RO data as they are needed, and unload them again once the processing is done?

Is this possible?

(I suppose data streams (on the filesystem level) could be used to solve this, but they aren't available to me (EXT3) and distribution would be tricky since data streams easily get lost.)

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

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

发布评论

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

评论(4

扛起拖把扫天下 2024-08-17 01:11:17

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

No, if it's part of the ELF file, it will be mapped. I'm not sure of the particulars of ELF, but if this was a PE file, you could simply tag on your added data to the end of the PE file, beyond the PE structure. Data that isn't part of the PE structure doesn't get mapped to memory in windows. I suspect the same exists in ELF.

风追烟花雨 2024-08-17 01:11:16

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

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

This is (very probably) already taken care of for you.

The real answer of course will be system-dependent, but in general, modern operating systems (and certainly Linux) use demand paging for executables, so no RAM will be actually allocated for sections of the ELF file you don't reference.

夜雨飘雪 2024-08-17 01:11:16

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

Instead of linking your blobs into the binary, append them to it. They won't be mapped, but you can read or map them as you need them.

铃予 2024-08-17 01:11:16

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

证明:

$ 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 部分,最简单的方法是映射整个文件。

Some answers are somewhat misleading as they imply that the whole binary will be mapped. No, that's wrong. Not everything will be mapped!

Proof:

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

That's the only two parts from the that will be mapped. Why? Because these are the only ones that have the type 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

You'll also notice that the virtual address is the same as defined in the ELF file.

In practice you'll only have access to the first 40 KiB (0x8052000-0x8048000 = 40960 Bytes) of the file. This is enough for the ELF headers but you won't be able to access say the DWARF .debug headers, let alone the string table (.strtab).

If you want access to all ELF sections, the easiest would be to map the whole file.

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