This is an archive of the discontinued LLVM Phabricator instance.

[LLD][ELF][ARM] Support /DISCARD/ of subset of .ARM.exidx sections
ClosedPublic

Authored by psmith on May 10 2020, 4:05 AM.

Details

Summary

Both the .ARM.exidx and .eh_frame sections have a custom SyntheticSection that acts as a container for the InputSections. The InputSections are added to the SyntheticSection prior to /DISCARD/ which limits the affect a /DISCARD/ can have to the whole SyntheticSection. In the majority of cases this is sufficient as it is not common to discard subsets of the InputSections. The Linux kernel has one of these scripts which has something like:

/DISCARD/ : { *(.ARM.exidx.exit.text) *(.ARM.extab.exit.text) ... }

The .ARM.exidx.exit.text are not discarded because the InputSection has been transferred to the Synthetic Section. The *(.ARM.extab.exit.text) sections have not so they are discarded. When we come to write out the .ARM.exidx sections the dangling references from .ARM.exidx.exit.text to .ARM.extab.exit.text currently cause relocation out of range errors, but could as easily cause a fatal error message if we check for dangling references at relocation time.

This patch attempts to respect the /DISCARD/ command by running it on the .ARM.exidx InputSections stored in the SyntheticSection.

The .eh_frame is in theory affected by this problem, but I don't think that there is a dangling reference problem that can happen with these sections.

Fixes remaining part of pr44824 (https://bugs.llvm.org/show_bug.cgi?id=44824)

Diff Detail

Event Timeline

psmith created this revision.May 10 2020, 4:05 AM
MaskRay accepted this revision.May 10 2020, 10:14 PM

If I understand it correctly,

combineEhSections()
  .ARM.exidx.* are removed from inputSections
script->processSectionCommands()
  /DISCARD/ is handled. computeInputSections can find the synthetic section .ARM.exidx but not individual .ARM.exidx.*
writeResult<ELFT>()
  ...
    writeSections
      ARMExidxSyntheticSection::writeTo called on .ARM.exidx.exit.text which should have been discarded. This causes a relocation overflow

This patch tactfully introduces a mechanism to discard such synthetic sections. Looks great! One nit about an unneeded function.

lld/ELF/LinkerScript.cpp
453

Delete the function which is only called once.

491

cmd->sectionBases = computeInputSections(cmd, inputSections);

This revision is now accepted and ready to land.May 10 2020, 10:14 PM

Thanks for the review. I've applied the suggestion to remove the function.

This introduces a mechanism to discard individual .ARM.exidx.foo sections from the ARMExidx SyntheticSection. To explain the original problem a bit better:
.ARM.exidx are Exception Index sections. They form an ordered table that can be binary searched to find the unwinding instructions for an exception coming from a given address. If the unwind information is small then it is inlined into the .ARM.exidx section. If the unwind information is large a .ARM.extab section is created to contain the unwind information, the .ARM.exidx section entry then becomes a pc-relative reference to the .ARM.extab.

.text.small <- SHF_LINK_ORDER .ARM.exidx.small
.text.large <- SHF_LINK_ORDER .ARM.exidx.large -> .ARM.extab.large

If /DISCARD/ contains both .ARM.exidx.large and .ARM.extab.large then if we only discard .ARM.extab.large (due to .ARM.exidx.large being hidden away in the SyntheticSection, then .ARM.exidx.large has a dangling reference which causes an error at relocation time.

This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptMay 11 2020, 6:56 AM