[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:25:34 PDT 2024
nico wrote:
Here's the promised proof-of-concept with a linker script. The only way I found to set section flags is by using custom `PHDRS` (…which only sets segment flags, not section flags). prot-elf.cc as above, and then:
```
% cat prot-elf.ld
PHDRS
{
headers PT_PHDR PHDRS ;
interp PT_INTERP ;
text PT_LOAD FILEHDR PHDRS ;
data PT_LOAD ;
readonly PT_LOAD FLAGS (4) ;
dynamic PT_DYNAMIC ;
}
SECTIONS {
. = SIZEOF_HEADERS;
.interp : { *(.interp) } :text :interp
.text : { *(.text) } :text
.rodata : { *(.rodata) } /* defaults to :text */
. = . + 0x1000; /* move to a new page in memory */
.data : { *(.data) } :data
.dynamic : { *(.dynamic) } :data :dynamic
. = . + 0x1000; /* move to a new page in memory */
.mydata :
{
*(.mydata)
} : readonly
}
```
```
% ~/src/chrome/src/third_party/llvm-build/Release+Asserts/bin/clang --target=x86_64-pc-linux prot-elf.cc -fuse-ld=lld --sysroot ~/src/chrome/src/build/linux/debian_bullseye_amd64-sysroot -Wl,-T,prot-elf.ld
```
```
Sections look wrong:
% out/gn/bin/llvm-readelf -S a.out
out/gn/bin/llvm-readelf: warning: 'a.out': invalid PT_DYNAMIC size (0x1d8)
out/gn/bin/llvm-readelf: warning: 'a.out': PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used
There are 32 section headers, starting at offset 0x12d8:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
*snip*
[23] .mydata PROGBITS 0000000000002a50 000a50 000017 00 WA 0 0 16
*snip
```
But segments look right:
```
% out/gn/bin/llvm-readelf --segments a.out
out/gn/bin/llvm-readelf: warning: 'a.out': invalid PT_DYNAMIC size (0x1d8)
out/gn/bin/llvm-readelf: warning: 'a.out': PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used
Elf file type is DYN (Shared object file)
Entry point 0x610
There are 6 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x000150 0x000150 R 0x8
INTERP 0x000190 0x0000000000000190 0x0000000000000190 0x000478 0x000478 R 0x8
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000870 0x000870 R E 0x1000
LOAD 0x000870 0x0000000000001870 0x0000000000001870 0x0001e0 0x0001e0 RW 0x1000
LOAD 0x000a50 0x0000000000002a50 0x0000000000002a50 0x000060 0x000061 R 0x1000
DYNAMIC 0x000878 0x0000000000001878 0x0000000000001878 0x0001d8 0x0001d8 RW 0x8
Section to Segment mapping:
Segment Sections...
00
01 .interp .note.ABI-tag .dynsym .gnu.version .gnu.version_r .gnu.hash .dynstr .rela.dyn .rela.plt .rodata.cst4 .rodata.str1.1 .eh_frame_hdr .eh_frame
02 .interp .note.ABI-tag .dynsym .gnu.version .gnu.version_r .gnu.hash .dynstr .rela.dyn .rela.plt .rodata.cst4 .rodata.str1.1 .eh_frame_hdr .eh_frame .text .init .fini .plt
03 .data .dynamic .fini_array .init_array .got
04 .mydata .tm_clone_table .data.rel.local .got.plt .bss
05 .dynamic .fini_array .init_array .got
None .comment .symtab .shstrtab .strtab
```
This works, but making it production-quality requires a much longer and more complicated linker script per platform.
On the other hand, this PR (plus a follow-up `--section-ailgn=` PR) is small and makes this much easier to use for applications.
https://github.com/llvm/llvm-project/pull/109454
More information about the llvm-commits
mailing list