代码(.text)不是仅执行的? .rodata是可执行的吗?

时间:2016-05-18 23:54:56

标签: linux-kernel elf

我试图了解ELF段是如何进行内存映射的。我注意到各个部分都映射到同一个ELF段。例如,.rodata映射到与.text。

相同的段

为什么会这样?为什么不将.rodata映射到单独的只读且不可执行的段?

此外,将.text部分映射到"仅执行"它需要什么?细分(不可读)?是否存在可能阻碍此问题的内核/硬件限制?

编辑: 我可以补充一点,我正在使用GNU链接器,如果这有所不同。

3 个答案:

答案 0 :(得分:7)

收集上述评论

在包括x86-64在内的多种计算机体系结构中,无法将内存标记为可执行但不可读。

虽然x86 16位和32位确实允许在传统模式中进行分段,并且理论上可以使用内存段将内存标记为仅可执行文件,但是平面地址空间的优势非常大,现在x86-64 { {3}}:

  

3.2.4 IA-32e模式中的分段

     

在Intel 64架构的IA-32e模式中,分段的影响取决于处理器是以兼容模式还是64位模式运行。在兼容模式下,分段的功能与使用传统的16位或32位保护模式语义一样。

     

在64位模式下,通常(但不是完全)禁用分段,从而创建平坦的64位线性地址空间。处理器将CS,DS,ES,SS的分段基数视为零,创建一个等于有效地址的线性地址。 FS和GS部分是例外。这些段寄存器(保存段基)可用作线性地址计算中的附加基址寄存器。它们有助于解决本地数据和某些操作系统数据结构。

     

请注意,处理器不会在运行时以64位模式执行段限制检查。

因此,内核只需将其段设置为覆盖整个地址空间,而不依赖于分段来实现内存保护。

他们使用的是页面表的属性。进程内存映射中存在的每个页面都有一个页表条目,用于控制对它的访问。可以看到它们的格式概述mostly ignores its segments registers,但最重要的是有两个位控制允许的访问类型:

  • 位1(R / W):0表示只读,1表示读写。
  • 位63(XD):0表示可执行,1表示不可执行。

无法使用这些标志指示可执行文件 - noread-nowrite组合。如果页面完全存在于内存映射中,则它必须是可读的。

英特尔最新的微体系结构Skylake正在迅速采用一种解决方案,允许只执行内存:这是功能受洗的MPK(here),支持最近刚刚发布的Linux内核4.6。密钥占用页表条目的四位62:59,内存区域可以用表示执行noread-nowrite访问的键标记。

答案 1 :(得分:-1)

% objdump -h /bin/ls

/bin/ls:     file format elf64-x86-64

Sections:     
Idx Name          Size      VMA               LMA               File off  Algn
  0 .interp       0000001c  0000000000400238  0000000000400238  00000238  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  0000000000400254  0000000000400254  00000254  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  0000000000400274  0000000000400274  00000274  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     000000c0  0000000000400298  0000000000400298  00000298  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000cd8  0000000000400358  0000000000400358  00000358  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       000005dc  0000000000401030  0000000000401030  00001030  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  00000112  000000000040160c  000000000040160c  0000160c  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000070  0000000000401720  0000000000401720  00001720  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rela.dyn     000000a8  0000000000401790  0000000000401790  00001790  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rela.plt     00000a98  0000000000401838  0000000000401838  00001838  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         0000001a  00000000004022d0  00000000004022d0  000022d0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000720  00000000004022f0  00000000004022f0  000022f0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .text         0001112a  0000000000402a10  0000000000402a10  00002a10  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .fini         00000009  0000000000413b3c  0000000000413b3c  00013b3c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .rodata       00006754  0000000000413b80  0000000000413b80  00013b80  2**6
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 15 .eh_frame_hdr 0000081c  000000000041a2d4  000000000041a2d4  0001a2d4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame     00002c7c  000000000041aaf0  000000000041aaf0  0001aaf0  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .init_array   00000008  000000000061de00  000000000061de00  0001de00  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 18 .fini_array   00000008  000000000061de08  000000000061de08  0001de08  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 19 .jcr          00000008  000000000061de10  000000000061de10  0001de10  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 20 .dynamic      000001e0  000000000061de18  000000000061de18  0001de18  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 21 .got          00000008  000000000061dff8  000000000061dff8  0001dff8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got.plt      000003a0  000000000061e000  000000000061e000  0001e000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 23 .data         000002a0  000000000061e3c0  000000000061e3c0  0001e3c0  2**6
                  CONTENTS, ALLOC, LOAD, DATA
 24 .bss          00000e08  000000000061e680  000000000061e680  0001e660  2**6
                  ALLOC

每个部分都有自己的attrs,例如READONLYCONTENTSALLOCLOADDATA

具有相同attrs的部分可以一起映射。

根据elf format

   sh_flags  Sections support one-bit flags that describe miscellaneous
             attributes.  If a flag bit is set in sh_flags, the
             attribute is "on" for the section.  Otherwise, the
             attribute is "off" or does not apply.  Undefined attributes
             are set to zero.

             SHF_WRITE      This section contains data that should be
                            writable during process execution.

             SHF_ALLOC      This section occupies memory during process
                            execution.  Some control sections do not
                            reside in the memory image of an object
                            file.  This attribute is off for those
                            sections.

             SHF_EXECINSTR  This section contains executable machine
                            instructions.

             SHF_MASKPROC   All bits included in this mask are reserved
                            for processor-specific semantics.

ELFSHF_EXECINSTR部分attr,因此编译器或链接没有设置attr。

答案 2 :(得分:-1)

section和segment是两个不同的概念,程序加载使用segment时,甚至可以剥离section表。一个细分可以包含多个部分。 .rodata和.text都是只读的。因此可以将它们放在同一段中。