This is an archive of the discontinued LLVM Phabricator instance.

[ELF][ARM] Fix /DISCARD/ of section with .ARM.exidx section
ClosedPublic

Authored by peter.smith on Aug 5 2019, 10:50 AM.

Details

Summary

The combineEhSections runs, by design, before processSectionCommands so that input exception sections like .ARM.exidx and .eh_frame are not assigned to OutputSections. Unfortunately if /DISCARD/ removes InputSections that have associated .ARM.exidx sections without discarding the .ARM.exidx synthetic section then we will end up crashing when trying to sort the InputSections in ascending address order.

We fix this by filtering out the sections that have been discarded prior to processing the InputSections in finalizeContents()

fixes pr42890

Note that we cannot discard a subset of the .ARM.exidx table in LLD as by the time the /DISCARD/ has been evaluated it is a single synthetic section called .ARM.exidx. I'm not too concerned about this as a partial discard doesn't make a lot of sense as LLD creates synthetic entries to fill any gaps in the table.

I don't think that this affects .eh_frame as we don't have the dependent section and ordering requirements that we do for .ARM.exidx.

Diff Detail

Repository
rL LLVM

Event Timeline

peter.smith created this revision.Aug 5 2019, 10:50 AM

Haven't gone through the logic yet (and I'm still learning the .ARM.exidx mechanism), but the solution looks good.

In the description, several .ehframe occurrences should be replaced by .eh_frame. Some nits inlined.

ELF/SyntheticSections.cpp
3209 ↗(On Diff #213402)

with a -> with a dependent?

3212 ↗(On Diff #213402)

std::remove_if(excutableSections.begin(), excutableSections.end(), ...) -> llvm::remove_if(excutableSections, ...)

3217 ↗(On Diff #213402)

llvm::remove_if

grimar added inline comments.Aug 6 2019, 12:15 AM
ELF/SyntheticSections.cpp
3212 ↗(On Diff #213402)

The following should work here (and below):
llvm::erase_if(executableSections, isDiscarded);

test/ELF/arm-exidx-partial-discard.s
6 ↗(On Diff #213402)

Seems you could combine this llvm-readobj calls?

MaskRay added inline comments.Aug 6 2019, 3:07 AM
test/ELF/arm-exidx-partial-discard.s
6 ↗(On Diff #213402)

Alternatively, | FileCheck --implicit-check-not=.exit.text /dev/null

peter.smith edited the summary of this revision. (Show Details)

Thanks very much for the comments. I've updated the description, comment, used llvm::erase_if and combined the llvm-readobj into one call.

The full details are in https://static.docs.arm.com/ihi0038/a/IHI0038A_ehabi.pdf although only a small part is relevant to linking. The biggest complications that lead to us using a SyntheticSection were:

  • Adjacent table entries with identical unwind entries can be merged.
  • The address range covered by table entry N is terminated by table entry N + 1. This means that if the .ARM.exidx information is incomplete (executable sections don't have any unwinding information) then an exception thrown through a function without any unwinding information can match a table entry with unwinding information. We fix this by generating CANT_UNWIND table entries for sections without any unwind information.
  • A terminating CANT_UNWIND sentinel entry is required to terminate the address range of the last table entry.

Let me know if you have any questions, I've glossed over a lot of detail.

ruiu accepted this revision.Aug 6 2019, 5:30 AM

LGTM

This revision is now accepted and ready to land.Aug 6 2019, 5:30 AM
MaskRay accepted this revision.Aug 6 2019, 5:34 AM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptAug 6 2019, 7:13 AM