This is an archive of the discontinued LLVM Phabricator instance.

[ARM][LLD] Add support for .ARM.exidx sections
AbandonedPublic

Authored by peter.smith on Sep 19 2016, 8:32 AM.

Details

Summary

This is another attempt at implementing support for .ARM.exidx sections to lld.

Apologies for the delay since submitting the last update.

previous reviews for reference:
https://reviews.llvm.org/D24032 (Original)
https://reviews.llvm.org/D24258 (Custom Input and Output Sections)

standards for reference:

In summary the minimum I think we need to do to support .ARM.exidx sections are:

  • Relocatable objects need to maintain the SHF_LINK_ORDER dependency between .ARM.exidx and the executable section.
  • .ARM.exidx sections need to be protected from Garbage Collection
  • The .ARM.exidx output section in a full link needs to be ordered
  • The PT_ARM_EXIDX program header should be generated to describe the .ARM.exidx output section.

I've tried to follow as best I can the suggestions in the previous reviews:

  • Sort the .ARM.exidx sections post relocation, rather than using the SHF_LINK_ORDER dependency prior to relocation.
  • Do not combine InputSections subject to a SHF_LINK_ORDER dependency when doing a relocatable link.

I think I've had mixed success. There are less overall changes but I'm not sure if it has made the implementation significantly simpler.

Review notes:

Preserving the SHF_LINK_ORDER flag and sh_link field in relocatable objects:

For relocatable objects we remove the need to reorder the .ARM.exidx sections by not combining the .ARM.exidx sections with SHF_LINK_ORDER, and the sections that the .ARM.exidx sections identify with their sh_link field[*].

Stopping the combination of .ARM.exidx sections into a single Output section is simple, stopping the combination of sections that the .ARM.exidx sections have a sh_link to is more difficult as we don't know for an InputSection if there is an .ARM.exidx section that has a sh_link to it.

The approach I went for was to detect the dependency when loading InputSections from an object, and setting a "do not combine me flag" in InputSection called RelocatableOrphan.

  • I tried to see if we could get away with just not combining the .ARM.exidx sections and leaving the executable sections untouched (multiple .ARM.exidx sections with the same .sh_link value). GNU ld was happy with the output objects but gold was not, giving an error message that specifically disallowed more than one SHF_LINK_ORDER sections having the same sh_link value.

Reordering the .ARM.exidx section.

The .ARM.exidx section is made up of a table of entries, with each entry consisting of two 4 byte fields.

offset to function from placeaction to take for function

An entry can take one of three forms

PREL31 offset to function0x00000001 for special .cantunwind
PREL31 offset to functionbit 31 set for Inline Table Entry
PREL31 offset to functionbit 31 clear for PREL31 offset to .ARM.ehtab entry

The table entries must be sorted in ascending order of virtual address of function. Note that the offsets to a function in a correctly ordered table are not guaranteed to be monotonically increasing.

To reorder the table post relocation we must find a key and fix up the offsets post reordering. The approach taken here is to convert the PREL31 offsets to absolute addresses, sort on VA of the function, then convert back to PREL31 offsets.

The one complication is fixing up the PREL31 offset to .ARM.ehtab entry, while leaving inline table entries and .cantunwind entries alone. The virtual address of the inline table entry may have bit 31-set so we use bit 0 of the address of the function (which will be clear as Thumb functions are at a minimum 2 byte aligned) to record that an action is a PREL31 offset.

Protecting .ARM.exidx sections from Garbage Collection
There are no relocations to .ARM.exidx sections so we must protect them from garbage collection. There is scope for optimization here as .ARM.exidx section is only live if the executable section it links to is live.

PT_ARM_EXIDX program header
This is equivalent to the PT_GNU_EH_FRAME program header and just identifies the combined .ARM.exidx section.

Diff Detail

Event Timeline

peter.smith retitled this revision from to [ARM][LLD] Add support for .ARM.exidx sections.
peter.smith updated this object.
peter.smith added reviewers: ruiu, rafael, grimar.
peter.smith added a subscriber: llvm-commits.
ruiu added inline comments.Sep 19 2016, 4:29 PM
ELF/InputFiles.cpp
258–261

This function returns true if we do not want to merge a section under --relocation option. I'm wondering if it should always return true for anything. In other word, we are able to not merge any section at all if --relocation is given. It'll change the current behavior, but I don't think it would do any harm.

ELF/MarkLive.cpp
253

You want to add S.startswith(".ARM.exidx") to isReserved` instead.

ELF/OutputSections.cpp
883

nit: remove {}

890

Please add () for & because I (and probably a lot of people) don't memorize which has higher precedence, & or &&.

890

Can you please add a comment what this new code is for? (I think I know it now but probably it is a bit mysterious for first time readers.)

ELF/Writer.cpp
1109

Indentation

1392

Can you run clang-format-diff on this patch? A function comment would be appreciated.

1411

Please add a function comment.

1414–1415

I think you want to use ulittle32_t so that it will work even on big-endian machines.

1466–1467
if (auto *OS = dyn_cast<OutputSection<ELFT>>(ARMEidx))
grimar added inline comments.Sep 20 2016, 1:24 AM
ELF/OutputSections.cpp
894
if (auto *D = getLinkOrderDependency(this->Sections.front()))
  this->Header.sh_link = D->OutSec->SectionIndex;
ELF/Writer.cpp
1085

First check looks excessive for me, I guess only EM_ARM can have SHT_ARM_EXIDX anyways.

1417

We probably more often do not use auto in such short expressions for casting pointers,
though no general rule I think, but I would write without.

1422
(ARMExidxEntry &A, ARMExidxEntry &B)
1466

I would probably rewrite this as

if (!Config->Relocatable)
    if (auto *OS = dyn_cast_or_null<OutputSection<ELFT>>(findSection(".ARM.exidx")))
      SortARMExidx(...)
test/ELF/arm-exidx-order.s
16

one line for comment ?

28

"as a" (double space)

Thank you both for the comments.

Updated diff to address code-review comments.

It is an interesting question as to whether to merge sections during a relocatable link. ARM's proprietary linker has this policy although it calls its option partial linking rather than relocatable. This had the advantage of allowing the final link to do a better job with garbage collection as prematurely merged sections can't be picked apart in the final link. The two primary use cases for partial linking were placement in the armlink equivalent of a linker script; and performance, large static links could be sped up a small amount by building a partial object in place of a library.

The only advantages I can think of for merging sections at relocatable link time are that it would be faster as the linker has done more of the work of the final link. There might be some use case for a company distributing a single binary only object to a customer and the relocatable link makes this possible to guarantee the order of sections.

In summary I don't think that merging sections makes a difference to the vast majority of users, but it makes the linker less of a drop-in replacement for GNU ld as in some cases it will behave differently.

Would it be simpler/helpful if I split out the support for .ARM.exidx sections in executables/shared-libraries and remove support for relocatable links?

Given that the primary use case for relocatable links is C only kernel modules, I think it would be ok for now to not support ordering of .ARM.exidx sections in relocatable links. My preference would be to discard the .ARM.exidx sections as clang will output a .ARM.exidx can't unwind section even for C code even if -fno-exceptions is used.

This should simplify the patch, and we would at least know what we'd need to do if it became necessary to support it later.

ELF/Writer.cpp
1085

Unfortunately the section type for SHT_ARM_EXIDX 0x70000001 is in the processor specific extensions field of ELF so it isn't unique. The same value is used by SHT_X86_64_UNWIND.

I've done some experiments to split out the relocatable links from the application and whilst it does simplify the patch it does have some complications surrounding what to do with .ARM.exidx sections during a relocatable link. In particular it is quite difficult to give a useful warning that .ARM.exidx sections aren't supported.

In summary:

  • Clang will output a .cantunwind .ARM.exidx table even for C code compiled without exceptions. If we were to give a warning that .ARM.exidx wasn't supported for relocatable links it would be given for every relocatable link even if the .ARM.exidx sections were never used. It could be possible to scan the .ARM.exidx sections and assume that if all of the entries were .cantunwind then no warning is needed, however this is starting to put the complexity back in.
  • We can't completely ignore .ARM.exidx sections as the combined output .ARM.exidx will have the SHF_LINK_ORDER flag and an incorrect sh_link field. This is likely to cause problems if the object is used in a subsequent link.
    • Just taking off the SHF_LINK_ORDER flag and clearing the sh_link field causes a warning from ld.bfd
    • Discarding the .ARM.exidx sections and any associated relocations does work, although it does need some extra code in InputFiles to do this.

My preference would be to implement support for relocatable objects. Given that there aren't many serious users of lld for ARM I think it would be possible for a short time to split out the relocatable alterations with lld discarding all .ARM.exidx sections in a relocatable link, but I think it would need fixing rather than leaving it unsupported.

Updated patch to rebase and to alter the arm-exidx-order test to be less sensitive to address changes. No functional changes to test code.

I'll split out the relocatable part into a separate patch under a separate review. At a conference right now so it might be a couple of days.

peter.smith abandoned this revision.Oct 10 2016, 3:58 AM

Abandoning this revision as the majority of the changes in here have been transferred to:
D25234 and D25127

The missing part is support for relocatable ld -r links. This will be coming in a future set of patches.