.text与.data所需的对齐方式 [英] Required alignment of .text versus .data

查看:44
本文介绍了.text与.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(0x100); 也可以, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆