Reputation: 2412
I am trying to understand how ELF segments are memory mapped. I noticed that various sections are mapped to the same ELF segment. For example, .rodata is mapped to the same segment as .text.
Why is this the case? Why not map .rodata to a separate read-only and not executable segment?
Also, what does it entail to map the .text section to an "execute ONLY" segment (not readable)? Are there any kernel/HW limitations that may hinder this?
EDIT: I may as well add that I am using the GNU linker, if that makes a difference.
Upvotes: 6
Views: 2911
Reputation: 328
section and segment are two different concept, program load use segment, you can even strip section table. a segment can contain multiple sections. .rodata and .text both are read only. so they can be put to same segment.
Upvotes: -1
Reputation: 13457
Gathered from comments above
It is not possible on several computer architectures, including x86-64, to mark memory as executable but not readable.
While x86 16- and 32-bit did allow segmentation in legacy modes, and memory segments could in theory be used to mark memory as executable-only, the benefits of a flat address space were so great that x86-64 now mostly ignores its segments registers:
3.2.4 Segmentation in IA-32e Mode
In IA-32e mode of Intel 64 architecture, the effects of segmentation depend on whether the processor is running in compatibility mode or 64-bit mode. In compatibility mode, segmentation functions just as it does using legacy 16-bit or 32-bit protected mode semantics.
In 64-bit mode, segmentation is generally (but not completely) disabled, creating a flat 64-bit linear-address space. The processor treats the segment base of CS, DS, ES, SS as zero, creating a linear address that is equal to the effective address. The FS and GS segments are exceptions. These segment registers (which hold the segment base) can be used as additional base registers in linear address calculations. They facilitate addressing local data and certain operating system data structures.
Note that the processor does not perform segment limit checks at runtime in 64-bit mode.
Kernels thus simply set their segments to cover the entire address space and do not rely on segmentation to achieve memory protection.
What they do use is the page table's attributes. Every page that exists in a process's memory map has a page table entry governing access to it. An overview of their format can be seen here, but most crucially there are two bits that control what type of access is permitted:
It is not possible to indicate an executable-noread-nowrite combination with these flags. If the page is at all present in the memory map, it must be readable.
A solution is fast approaching in Intel's latest microarchitecture, Skylake, which will allow execute-only memory: It is the feature baptized MPK (memory protection keys), support for which landed in Linux kernel 4.6 just recently released. The keys occupy the four bits 62:59 of the page table entry, and areas of memory can be tagged with a key indicating execute-noread-nowrite access.
Upvotes: 8
Reputation: 5275
% 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
Each section has its own attrs, like READONLY
, CONTENTS
, ALLOC
, LOAD
, DATA
sections with same attrs can be mapped together.
According to 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.
ELF
has SHF_EXECINSTR
section attr, so it is the compiler or link doesn't set the attr.
Upvotes: -1