【发布时间】:2020-07-19 02:40:52
【问题描述】:
我正在寻找一些帮助来理解 parse_elf() 中的解压缩 Linux 映像在 arch/x86/boot/compressed/misc.c 中的解析。具体来说,我不明白 ELF 段被复制到和从哪些内存区域。下面是一些带注释的代码,显示了我的(错误)理解。
for (i = 0; i < ehdr.e_phnum; i++) { // For each segment...
phdr = &phdrs[i];
switch (phdr->p_type) { // Ignore all segments that
case PT_LOAD: // aren't labeled as loadable
#ifdef CONFIG_RELOCATABLE
dest = output; // Set `dest` to be equal to the base of the kernel
// after decompression and KASLR considerations
// Next, add to `dest` the difference between the physical address
// of the segment and where the kernel was told to be loaded by the
// kernel configuration file. It seems to me that this difference
// is equal to `phdr->p_offset`.
dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
#else
// If we aren't considering relocations then just use the physical
// address of the segment as the destination.
dest = (void *)(phdr->p_paddr);
#endif
// Copy, to the destination determined above, from the beginning
// of the decompressed kernel plus the offset to the segment until
// the end of the segment is reached.
memcpy(dest,
output + phdr->p_offset,
phdr->p_filesz);
break;
default: /* Ignore other PT_* */ break;
}
}
令人困惑的是,在重定位的情况下,memcpy 的第一个和第二个参数似乎是相同的,调用parse_elf 毫无意义。可能是我误解了LOAD_PHYSICAL_ADDR或phdr->p_paddr是什么,或者内核解压到位后采取的步骤。
非重定位情况更有意义,因为我们只需从解压缩的内核复制到“硬编码”地址。
【问题讨论】:
-
为什么你期望
phdr->p_paddr - LOAD_PHYSICAL_ADDR等于phdr->p_offset? -
我目前的理解是
phdr->p_paddr是一个绝对物理地址,指向解压内核中段的开头。LOAD_PHYSICAL_ADDR是内核开始的物理地址。因此,通过减去它们,我们得到内核开始(ELF 的开始)和与phdr->p_offset相同的段之间的差异。
标签: linux linux-kernel elf