【问题标题】:why segments in elf file can overlap为什么elf文件中的段可以重叠
【发布时间】:2012-06-07 23:01:48
【问题描述】:

简单的 C 文件:

#include <stdio.h>
int main(){
    printf("Hello World");
    return 0;
}

编译代码后,使用readelf -a a.out,elf信息如下:

问题:

  1. 多个部分出现在不同的段中,例如第 2 段和第 3 段中的 interp 部分。一个部分如何出现在多个段中?
  2. 第二个段的地址从 0x8048134 开始,但第三个 LOAD 段从 0x8048000 开始,内存大小为 0x004d0。那么这两个部分重叠?两个段如何在内存中重叠?
  3. 为什么程序头的偏移量和 viraddr 必须以页面大小为模一致?

【问题讨论】:

    标签: assembly elf segment


    【解决方案1】:

    部分表中可能有垃圾,或者它可能完全丢失。对动态加载器而言,重要的是段表(程序头),即便如此,只有 PT_LOAD 段不应重叠*。其他类型的段(INTERP、DYNAMIC 等)为加载程序提供附加信息,通常引用 LOAD 段的某些部分。

    *the spec 是这样说的:

    PT_LOAD 数组元素指定一个可加载段,描述为 p_fileszp_memsz。文件中的字节映射到 内存段的开始。如果段的内存大小 (p_memsz) 大于文件大小 (p_filesz),“额外” 字节被定义为保存值 0 并遵循段的 初始化区域。文件大小不得大于内存 尺寸。程序头表中的可加载段条目出现在 升序,按p_vaddr 成员排序。

    如您所见,没有提到重叠,因此似乎没有被禁止,尽管我认为我没有看到任何具有重叠 PT_LOAD 段的文件。

    【讨论】:

    • 规范只说段必须以p_vaddr 的顺序出现。在我的理解中,这并不意味着它们不能重叠,而是意味着如果重叠的话,较高的细分优先于较早的细分。
    • 是的,这就是我在上一段中所说的。
    【解决方案2】:
    1. 多个部分出现在不同的段中,例如第 2 段和第 3 段中的 interp 部分。

    那么?

    一个部分如何出现在多个段中?

    为什么不呢?

    一个部分不会出现在多个PT_LOAD 段中,但.interp 同时出现在PT_LOADPT_INTERP 中没有任何问题。

    1. 两个段如何在内存中重叠?

    再说一遍,为什么不呢?

    1. 为什么程序头的偏移量和 viraddr 必须以页面大小为模一致?

    因为否则不可能mmap 段并让它出现在virtaddr

    【讨论】:

    • 当问号比问题包含更多个问号时,它仍然是答案吗?
    • 人们期望对显而易见的事情应该很容易向没有具有相同见解的人解释。你在这方面并没有特别成功。事实上,听起来你实际上并不知道答案。如果您这样做,您当然可以发布更好的答案吗?至少解释段和部分是如何相关的。
    • @HansPassant 我不知道如何更好地回答,因为我无法猜测 OP 有许多可能的误解中的哪一个,因此不知道要消除哪些。 “段和部分如何关联”——一个部分可能出现在 0、1 个或多个段中。可加载部分将恰好出现在 1 个PT_LOAD 段中(但可能出现在其他段中)。这有帮助吗? (我不希望它这样做,但我真的不明白你在问什么关于段和部分的问题。)
    • @HansPassant 哦,一个段可能包含 0、1 或更多部分。 PT_LOAD 段将包含至少 1 个部分。
    • 所以段只是告诉加载器在哪里可以找到内存和文件中的相应信息。那正确吗?顺便问一下,可以推荐这方面的任何资源吗?
    猜你喜欢
    • 2020-09-18
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 2015-02-19
    • 2014-08-30
    相关资源
    最近更新 更多