[llvm-dev] How LLD should create segments when linkerscript is used ?

Davide Italiano via llvm-dev llvm-dev at lists.llvm.org
Fri Aug 12 10:27:58 PDT 2016


+ Michael

On Fri, Aug 12, 2016 at 7:24 PM, George Rimar via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
> I wonder what is correct way to create PT_LOADs when linkerscript is used ?
> Currently we create new one for each section that changes access flags. But ld seems to do different thing.
>
> Imagine we have next sections:
> .section .AX.1,"ax"
> .quad 1
> .section .A.1,"a"
> .quad 2
> .section .AW.1,"aw"
> .quad 3
>
> And script:
> SECTIONS {
> . = ALIGN(CONSTANT (MAXPAGESIZE));
> .AX : { *(.AX.*) }
> . = ALIGN(CONSTANT (MAXPAGESIZE));
> .A : { *(.A.*) }
> . = ALIGN(CONSTANT (MAXPAGESIZE));
> .AW : { *(.AW.*) }
> }
>
> ld creates 2 segments here:
>   LOAD           0x0000000000200000 0x0000000000000000 0x0000000000000000
>                  0x0000000000200008 0x0000000000200008  R E    200000
>   LOAD           0x0000000000600000 0x0000000000400000 0x0000000000400000
>                  0x0000000000000008 0x0000000000000008  RW     200000
>  Section to Segment mapping:
>   Segment Sections...
>    00     .AX .text .A
>    01     .AW
>
> And if I change script in the next way:
> SECTIONS {
> . = ALIGN(CONSTANT (MAXPAGESIZE));
> .AX : { *(.AX.*) }
> . = ALIGN(CONSTANT (MAXPAGESIZE));
> .A : { *(.A.*) }
> .AW : { *(.AW.*) }
> }
>
> It will create single segment, combining access attributes:
>  LOAD           0x0000000000200000 0x0000000000000000 0x0000000000000000
>                  0x0000000000200010 0x0000000000200010  RWE    200000
>
> So looks like its behavior is to combine all sections before writable ones to single segment
> and create writable segment for others if possible, but if not it will create single segment for everything.
> I think FreeBSD script relies on this behavior. When linking with ld It has 2 PT_LOADS (RE + RW) when LLD creates 4 (R RE R RW),
> and since we do not align sections to the page boundary manually or in script, it will not work I think.
>
> Below is lld output of FreeBSD kernel (notice that RE and R loads are not aligned):
> Program Headers:
>   Type           Offset             VirtAddr           PhysAddr
>                  FileSiz            MemSiz              Flags  Align
>   PHDR           0x0000000000000040 0xffffffff80001040 0xffffffff80001040
>                  0x00000000000001f8 0x00000000000001f8  R      8
>   INTERP         0x0000000000000238 0xffffffff80001238 0xffffffff80001238
>                  0x000000000000000d 0x000000000000000d  R      1
>       [Requesting program interpreter: /red/herring]
>   LOAD           0x0000000000000000 0xffffffff80001000 0xffffffff80001000
>                  0x00000000000e410e 0x00000000000e410e  R      1000
>   LOAD           0x00000000000e4110 0xffffffff800e5110 0xffffffff800e5110
>                  0x0000000000ba2b0c 0x0000000000ba2b0c  R E    1000
>   LOAD           0x0000000000c86c20 0xffffffff80c87c20 0xffffffff80c87c20
>                  0x000000000038ab28 0x000000000038ab28  R      1000
>   LOAD           0x0000000001012000 0xffffffff81013000 0xffffffff81013000
>                  0x000000000012ae30 0x0000000000331e30  RW     1000
>   DYNAMIC        0x0000000001012000 0xffffffff81013000 0xffffffff81013000
>                  0x0000000000000080 0x0000000000000080  RW     8
>   GNU_RELRO      0x0000000001012000 0xffffffff81013000 0xffffffff81013000
>                  0x0000000000000080 0x0000000000000080  R      1
>   GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
>                  0x0000000000000000 0x0000000000000000  RW     0
>
> ld output of the same:
> Program Headers:
>   Type           Offset             VirtAddr           PhysAddr
>                  FileSiz            MemSiz              Flags  Align
>   PHDR           0x0000000000000040 0xffffffff80200040 0xffffffff80200040
>                  0x0000000000000150 0x0000000000000150  R E    8
>   INTERP         0x0000000000000190 0xffffffff80200190 0xffffffff80200190
>                  0x000000000000000d 0x000000000000000d  R      1
>       [Requesting program interpreter: /red/herring]
>   LOAD           0x0000000000000000 0xffffffff80200000 0xffffffff80200000
>                  0x0000000000fe2de8 0x0000000000fe2de8  R E    200000
>   LOAD           0x0000000000fe3000 0xffffffff813e3000 0xffffffff813e3000
>                  0x0000000000129430 0x00000000003313c0  RW     200000
>   DYNAMIC        0x0000000000fe3000 0xffffffff813e3000 0xffffffff813e3000
>                  0x00000000000000d0 0x00000000000000d0  RW     8
>   GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
>                  0x0000000000000000 0x0000000000000000  RWE    8
>
>
> So see next possible solutions:
> 1) Align first sections of each segment to the page boundary like we do for non-script case.
> 2) Implement the described ld behavior.
>
> Thoughts ?
>
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

-- 
Davide

"There are no solved problems; there are only problems that are more
or less solved" -- Henri Poincare


More information about the llvm-dev mailing list