[PATCH] D78422: [LLD][ELF][ARM] Fix ARM Exidx order for non monotonic section order

Peter Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 20 02:06:49 PDT 2020


psmith added a comment.

In D78422#1991026 <https://reviews.llvm.org/D78422#1991026>, @MaskRay wrote:

> The patch looks good. I think applying it does not hurt.
>
> > `// RUN:         .text.1 0x80000200 : AT(0x80000200) { *(.text.1) } \`
> >  `// RUN:         .text.2 0x80000100 : AT(0x80000100) { *(.text.2) } \`
>
> This is interesting. Does linux/arch/arm have such a use case where `VMA(.text.1) > VMA(.text.2)` with optional `LMA(.text.1) < LMA(.text.2)`? If it does, we probably should let it drop that requirement.


Difficult to tell, the linker script is generated from macros and is not easy to understand, I've untangled it a bit and expanded.

  __vectors_start = .; .vectors 0xffff0000 : AT(__vectors_start) { *(.vectors) } 
  . = __vectors_start + SIZEOF(.vectors); __vectors_end = .; 
  __stubs_start = .; .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) { *(.stubs) } 
  . = __stubs_start + SIZEOF(.stubs); __stubs_end = .
  ; PROVIDE(vector_fiq_offset = vector_fiq - ADDR(.vectors));
  . = ALIGN(8); 
  .init.text : AT(ADDR(.init.text) - 0) { _sinittext = .; *(.init.text .init.text.*) *(.text.startup) *(.meminit.text*) _einittext = .; }
  .exit.text : {
   *(.exit.text) *(.text.exit) *(.memexit.text)
  }

With a corresponding map file

  .vectors        0x00000000ffff0000       0x20 load address 0x0000000080b00000
   *(.vectors)
   .vectors       0x00000000ffff0000       0x20 arch/arm/kernel/entry-armv.o
                  0x0000000080b00020                . = (__vectors_start + SIZEOF (.vectors))
                  0x0000000080b00020                __vectors_end = .
                  0x0000000080b00020                __stubs_start = .
  
  .stubs          0x00000000ffff1000      0x2ac load address 0x0000000080b00020
   *(.stubs)
   .stubs         0x00000000ffff1000      0x2ac arch/arm/kernel/entry-armv.o
                  0x00000000ffff1240                vector_fiq
                  0x0000000080b002cc                . = (__stubs_start + SIZEOF (.stubs))
                  0x0000000080b002cc                __stubs_end = .
                  [!provide]                        PROVIDE (vector_fiq_offset = (vector_fiq - ADDR (.vectors)))
                  0x0000000080b002d0                . = ALIGN (0x8)
  
  .init.text      0x0000000080b002e0    0x32410
                  0x0000000080b002e0                _sinittext = .
   *(.init.text .init.text.*)

> For symbol assignments, lld has such a diagnostic:
> 
>   void LinkerScript::setDot(Expr e, const Twine &loc, bool inSec) {
>     uint64_t val = e().getValue();
>     if (val < dot && inSec)
>       error(loc + ": unable to move location counter backward for: " +
>             ctx->outSec->name);
> 
> 
> the only software I know (unintentionally) making use of this property is seabios but I have a patch to fix that (https://mail.coreboot.org/hyperkitty/list/seabios@seabios.org/thread/KBHQU4OLW2THG5Q5F5X7EWTQDJHKNVYC/ )
> 
> Not sure how the Linux kernel leverage non-increasing VMAs but the BFD logic does not make me feel comfortable that it can handle various corner cases well:
>  https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/ldlang.c;hb=49d1d1f53df552f0592b1cc4cc9a74db70d5ffa7#l5782

FWIW in embedded systems it is quite common to have linker scripts where different OutputSections need to be copied to various disjoint memory locations and these are often not in order of ascending address. I think it is common for these to be in ascending LMA though. These are almost always done with an explicit assignment of the OutputSection base address though. I will need to search to see what examples I can find online, most of the complicated embedded projects are not open source so it is difficult to get examples.

>> I think that this also affects the standard SHF_LINK_ORDER, I think resolveSHFLinkOrder() probably needs to be moved to a similar place.
> 
> My understanding is that when linked-to sections span multiple output sections, the order is unspecified. That said, I agree that respecting the VMA order instead of the section header table order seems more reasonable.
>  If we are going to support non-increasing VMAs, making generic SHF_LINK_ORDER aligns with .ARM.exidx should be preferable.
>  I'll still decipher more about BFD's non-increasing VMA support.
> 
>> This change moves the finalisation of .ARM.exidx till after the first call to AssignAddresses.
> 
> `assignAddresses`

I'll take a look to see what BFD supports. From looking at the linux kernel example it looks like it is assigning addresses to sections and symbols in a similar way to LLD. Instructions to reproduce the problem are in the PR if you are interested.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78422/new/

https://reviews.llvm.org/D78422





More information about the llvm-commits mailing list