.text与.data所需的对齐方式 [英] Required alignment of .text versus .data
问题描述
我一直在玩弄 ELFIO 库.其中一个示例,在特别是,允许从头开始创建ELF文件-定义节,段,入口点,并为相关节提供二进制内容.
I've been toying around with the ELFIO library. One of the examples, in particular, allows one to create an ELF file from scratch – defining sections, segments, entry point, and providing binary content to the relevant sections.
我注意到,一个程序中创建这样的段错误时选择代码段对准小于页尺寸(0×1000):
I noticed that a program created this way segfaults when the code segment alignment is chosen less than the page size (0x1000):
// Create a loadable segment
segment* text_seg = writer.segments.add();
text_seg->set_type( PT_LOAD );
text_seg->set_virtual_address( 0x08048000 );
text_seg->set_physical_address( 0x08048000 );
text_seg->set_flags( PF_X | PF_R );
text_seg->set_align( 0x1000 ); // can't change this
注意在同一示例中, .text
部分仅与0x10的倍数对齐:
NB that the .text
section is only aligned to multiples of 0x10 in the same example:
section* text_sec = writer.sections.add( ".text" );
text_sec->set_type( SHT_PROGBITS );
text_sec->set_flags( SHF_ALLOC | SHF_EXECINSTR );
text_sec->set_addr_align( 0x10 );
但是,数据段虽然通过相同的机制分别加载,却没有此问题:
However, the data segment, although loaded separately through the same mechanism, does not have this problem:
segment* data_seg = writer.segments.add();
data_seg->set_type( PT_LOAD );
data_seg->set_virtual_address( 0x08048020 );
data_seg->set_physical_address( 0x08048020 );
data_seg->set_flags( PF_W | PF_R );
data_seg->set_align( 0x10 ); // note here!
现在,在这种特定情况下,数据可以按设计放入已分配的页面中.不知道这是否有任何区别,但是我将其虚拟地址更改为0x8148020,结果仍然可以正常工作.
Now in this specific case the data fits by design within the page that's already allocated. Not sure if this makes any difference, but I changed its virtual address to 0x8148020 and the result still works fine.
这是 readelf
的输出:
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000001000 0x0000000008048000 0x0000000008048000
0x000000000000001d 0x000000000000001d R E 1000
LOAD 0x0000000000001020 0x0000000008148020 0x0000000008148020
0x000000000000000e 0x000000000000000e RW 10
当可执行段的对齐方式不是0x1000的倍数但数据0x10没问题时,为什么程序无法执行?
更新:以某种方式再次尝试 text_seg-> set_align(0x10); 代码>失败.页面大小为0x1000,有趣的是,工作程序的
VirtAddr
在这两个段中均未遵循该规则:
Update: Somehow on a second try text_seg->set_align( 0x100 );
works too, text_seg->set_align( 0x10 );
fails. The page size is 0x1000 and interestingly, the working program's VirtAddr
does not adhere to it in either segment:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000100 0x08048100 0x08048100 0x0001d 0x0001d R E 0x100
LOAD 0x000120 0x08148120 0x08148120 0x0000e 0x0000e RW 0x10
SIGSEGV'ing一:
The SIGSEGV'ing one:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000080 0x08048100 0x08048100 0x0001d 0x0001d R E 0x10
LOAD 0x0000a0 0x08148120 0x08148120 0x0000e 0x0000e RW 0x10
生成的ELF位于此处.
推荐答案
ELF ABI不需要将 VirtAddr
或 PhysAddr
进行页面对齐.(我相信)只要求
The ELF ABI does not require that VirtAddr
or PhysAddr
be page-aligned. (I believe) it only requires that
({Virt,Phys}Addr - Offset) % PageSize == 0
对于两个工作的二进制文件都是正确的,对于不工作的二进制文件则为false.
That is true for both working binaries, and false for the non-working one.
更新:
我看不到后者如何失败.
I don't see how this fails for the latter.
我们有: VirtAddr == 0x08048100
和 Offset == 0x80
(和 PageSize == 4096 == 0x1000
).
(0x08048100 - 0x80) % 0x1000 == 0x80 != 0
必须在align == 0x10时达成一致,对吗?
has to agree when align == 0x10, doesn't it?
否:它必须与页面大小一致(如我之前所说),否则内核将无法对该段进行 mmap
.
No: it has to agree with the page size (as I said earlier), or the kernel will not be able to mmap
the segment.
这篇关于.text与.data所需的对齐方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!