[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