The comment at the top of compareByFilePosition indicates that it relies
on stable_sort to preserve the order of synthetic sections. We were
using sort instead of stable_sort, however, leading to incorrect
synthetic section ordering.
Details
Diff Detail
- Build Status
Buildable 8271 Build 8271: arc lint + arc unit
Event Timeline
I discovered this because the .ARM.exidx end sentinel was getting incorrectly reordered away from the end of the section, leading to unwinding failing in certain binaries. CC @peter.smith, in case you've run into any similar issues.
Unfortunately, I'm not sure how to write a test case for this. I was using -ffunction-sections so I would end up with multiple .ARM.exidx.* sections, so there's a reasonable chance of the sentinel getting incorrectly reordered, but there's no guarantee, since it depends on the underlying std::sort implementation (which could potentially even be randomized). Any ideas?
I've not seen this myself, but I haven't done a lot of testing on this after the initial patch went in, which I think was stable_sort at the time. I agree it will be difficult to write a test that will trigger reliably on all platforms sort routine. I've no objections to the change, although it might be better to rewrite compareByFilePosition to be std::sort friendly. For example it is currently:
static bool compareByFilePosition(InputSection *A, InputSection *B) { // Synthetic doesn't have link order dependecy, stable_sort will keep it last if (A->kind() == InputSectionBase::Synthetic || B->kind() == InputSectionBase::Synthetic) return false; InputSection *LA = A->getLinkOrderDep(); InputSection *LB = B->getLinkOrderDep(); OutputSection *AOut = LA->getParent(); OutputSection *BOut = LB->getParent(); if (AOut != BOut) return AOut->SectionIndex < BOut->SectionIndex; return LA->OutSecOff < LB->OutSecOff; }
I think it could be rewritten as:
static bool compareByFilePosition(InputSection *A, InputSection *B) { // Only Synthetic with a link order dependency is the ARMExidxSentinelSection // There is only one of these and it must be last. if (A->kind() == InputSectionBase::Synthetic) return false; if (B->kind() == InputSectionBase::Synthetic) return true; InputSection *LA = A->getLinkOrderDep(); InputSection *LB = B->getLinkOrderDep(); OutputSection *AOut = LA->getParent(); OutputSection *BOut = LB->getParent(); if (AOut != BOut) return AOut->SectionIndex < BOut->SectionIndex; return LA->OutSecOff < LB->OutSecOff; }
@peter.smith Yeah changing compareByFilePosition should work for now, though stable_sort might be more future-proof. I'll leave that for @rafael and @ruiu to decide.
LGTM
ELF/LinkerScript.cpp | ||
---|---|---|
1087 | I think you don't have to write this comment here, as we use std::stable_sort everywhere for reproducibility. |
ELF/LinkerScript.cpp | ||
---|---|---|
1087 | I'll remove it before committing. |
I think you don't have to write this comment here, as we use std::stable_sort everywhere for reproducibility.