[lld] [lld/ELF] Add --override-section-flags flag (PR #109454)
Nico Weber via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 20 11:21:47 PDT 2024
nico wrote:
Here's the promised example of using this:
```
% cat prot-elf.cc
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
extern char my_data[];
__attribute__((section(".mydata"))) char my_data[] = "Initial read-only data";
int main() {
long pagesize = sysconf(_SC_PAGESIZE);
void* page_start = (void*)((unsigned long)my_data & ~(pagesize - 1));
if (mprotect(page_start, pagesize, PROT_READ | PROT_WRITE) == 0)
strcpy(my_data, "New writable data");
else
perror("mprotect failed");
}
```
```
$ out/gn/bin/clang prot-elf.cc -fuse-ld=lld -Wl,--override-section-flags=.mydata=a
```
```
$ ./a.out
-----------------------------------------------
56387607f000-563876080000 r--p 00000000 fd:01 19553804 /usr/local/google/home/thakis/src/llvm-project/a.out
563876080000-563876081000 r-xp 00000000 fd:01 19553804 /usr/local/google/home/thakis/src/llvm-project/a.out
563876081000-563876082000 r--p 00000000 fd:01 19553804 /usr/local/google/home/thakis/src/llvm-project/a.out
563876082000-563876083000 rw-p 00000000 fd:01 19553804 /usr/local/google/home/thakis/src/llvm-project/a.out
5638a883b000-5638a885c000 rw-p 00000000 00:00 0 [heap]
*snip*
-----------------------------------------------
my_data: 0x56387607f800; page start: 0x56387607f000
-----------------------------------------------
56387607f000-563876080000 rw-p 00000000 fd:01 19553804 /usr/local/google/home/thakis/src/llvm-project/a.out
563876080000-563876081000 r-xp 00000000 fd:01 19553804 /usr/local/google/home/thakis/src/llvm-project/a.out
563876081000-563876082000 r--p 00000000 fd:01 19553804 /usr/local/google/home/thakis/src/llvm-project/a.out
563876082000-563876083000 rw-p 00000000 fd:01 19553804 /usr/local/google/home/thakis/src/llvm-project/a.out
5638a883b000-5638a885c000 rw-p 00000000 00:00 0 [heap]
*snip*
-----------------------------------------------
```
```
$ readelf --segments a.out
There are 11 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x0000000000000268 0x0000000000000268 R 0x8
INTERP 0x00000000000002a8 0x00000000000002a8 0x00000000000002a8
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000008c8 0x00000000000008c8 R 0x1000
LOAD 0x00000000000008d0 0x00000000000018d0 0x00000000000018d0
0x00000000000002d0 0x00000000000002d0 R E 0x1000
LOAD 0x0000000000000ba0 0x0000000000002ba0 0x0000000000002ba0
0x00000000000001e0 0x0000000000000460 RW 0x1000
LOAD 0x0000000000000d80 0x0000000000003d80 0x0000000000003d80
0x0000000000000078 0x0000000000000079 RW 0x1000
DYNAMIC 0x0000000000000bb0 0x0000000000002bb0 0x0000000000002bb0
0x00000000000001a0 0x00000000000001a0 RW 0x8
GNU_RELRO 0x0000000000000ba0 0x0000000000002ba0 0x0000000000002ba0
0x00000000000001e0 0x0000000000000460 R 0x1
GNU_EH_FRAME 0x0000000000000818 0x0000000000000818 0x0000000000000818
0x0000000000000024 0x0000000000000024 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x0
NOTE 0x00000000000002c4 0x00000000000002c4 0x00000000000002c4
0x0000000000000020 0x0000000000000020 R 0x4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .dynsym .gnu.version .gnu.version_r .gnu.hash .dynstr .rela.dyn .rela.plt .rodata .mydata .eh_frame_hdr .eh_frame
03 .text .init .fini .plt
04 .fini_array .init_array .dynamic .got .relro_padding
05 .data .tm_clone_table .got.plt .bss
06 .dynamic
07 .fini_array .init_array .dynamic .got .relro_padding
08 .eh_frame_hdr
09
10 .note.ABI-tag
```
(In `--sections` output, `.mydata` looks like so:
```
[11] .mydata PROGBITS 0000000000000800 00000800
0000000000000017 0000000000000000 A 0 0 16
```
)
One effect of this is that .mydata ends up in a phrd with .rela.dyn .rela.plt .rodata etc, and when temporarily mapping the first page of .mydata writeable, parts of those other readonly sections temporarily become writeable too. This can be worked around by adding an object file first on the link line that has `.mydata` with page alignment. We can also add a `--section-alignment=glob=value` flag to make this easier later on.
https://github.com/llvm/llvm-project/pull/109454
More information about the llvm-commits
mailing list