If an output section description for .ARM.exidx ends with an assignment statement,
the value of the symbol should include the sentinel entry.
Details
- Reviewers
• rafael peter.smith ruiu - Commits
- rG5e9da2d06bf3: [ELF] Add a comment for ARMExidxSentinelSection::Highest; Use "= nullptr"…
rG5966d15943ad: [ELF] Fix an assignment command at the end of an .ARM.exidx section.
rLLD322066: [ELF] Add a comment for ARMExidxSentinelSection::Highest; Use "= nullptr"…
rL322066: [ELF] Add a comment for ARMExidxSentinelSection::Highest; Use "= nullptr"…
rLLD321154: [ELF] Fix an assignment command at the end of an .ARM.exidx section.
rL321154: [ELF] Fix an assignment command at the end of an .ARM.exidx section.
Diff Detail
Event Timeline
This looks sensible to me. One minor nit with the comment as the ABI does not mention a sentinel. We add it as some recent versions of libunwind depend on it being there (due to gold and ld.bfd generating one).
ELF/Writer.cpp | ||
---|---|---|
1275 | Strictly speaking the ABI doesn't require the .ARM.exidx to be terminated by a sentinel, but without one it does mean that the address range of the last entry would only be terminated by the end of the address space. Until recently libunwind depended on the presence of a sentinel. |
ELF/OutputSections.h | ||
---|---|---|
85 ↗ | (On Diff #126937) | I don't think we should change this function just fixing an edge case for .ARM.exidx and linker script. Isn't there any way that is less intrusive? Also, please avoid using a parameter with a default value in lld as much as possible. |
Thanks for the comments!
- Rebased on the top to embrace changes to deduplicate entries.
- Implemented method {{empty()}} to remove a sentinel if there are no other entries.
- Added a test to check that a sentinel is not removed by deduplication.
}+ if (Sections.empty())
+ continue;This is never true because of the sentinel, no?
I still have similar checks as a precaution for malicious linker scripts. See {{arm-data-prel.s}} as the example.
Thanks for the review, @rafael!
- RUN: ld.lld --no-merge-exidx-entries -T %t.script %t.o -shared -o %t.so
- RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s
+// REQUIRES: arm
Why the change from // to #?
I see that you have unified the comment style, so, in this update I use the same, minimizing the diff.
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s --check-prefix=DUMP
Please use a prefix on the new FileCheck run instead to reduce the diff
(or commit the prefix change first).
Fixed.
+ if (!Sections.empty() && isa<ARMExidxSentinelSection>(Sections.back())) {
All tests pass if I move the !Sections.empty() to an assert.
As removeUnusedSyntheticSections() is not perfect, I can cook up a malicious script like this:
--- a/test/ELF/arm-data-prel.s +++ b/test/ELF/arm-data-prel.s @@ -1,7 +1,8 @@ // RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o // RUN: echo "SECTIONS { \ -// RUN: .text : { *(.text) } \ -// RUN: .prel.test : { *(.ARM.exidx) } \ +// RUN: .text : { *(.text.0) } \ +// RUN: .prel.test : { *(.ARM.exidx.0) } \ +// RUN: .trap : { *(.ARM.exidx) *(.dummy) } \ // RUN: .prel.test.TEST1 : { *(.ARM.exidx.TEST1) } \ // RUN: .TEST1 : { *(.TEST1) } } " > %t.script // RUN: ld.lld --script %t.script %t.o -o %t @@ -32,7 +33,7 @@ _start: mov pc, lr .fnend - .section .text, "ax",%progbits + .section .text.0, "ax",%progbits // The generated .ARM.exidx section will refer to the personality // routine __aeabi_unwind_cpp_pr0. Provide a dummy implementation // to stop an undefined symbol error
Generally, I prefer my code to be safe. Although I must admit, that, with this script, lld still crashes, just a bit later, in OutputSection::finalize().
+ARMExidxSentinelSection *ARMExidxSentinelSection::create() {
+ if (Config->Relocatable)
+ return nullptr;
+
+ return make<ARMExidxSentinelSection>();
+}This is now trivial, please inline.
Done.
LGTM with that.
Thanks! I'll commit this if there will be no further comments.
lld/trunk/ELF/SyntheticSections.cpp | ||
---|---|---|
2573 ↗ | (On Diff #127666) | It looks like this function returns true if the parent section of this section is empty. That's different from what you'd expect for emptyfunction. empty should return true if this is empty, not other object. |
lld/trunk/ELF/SyntheticSections.h | ||
790 ↗ | (On Diff #127666) | = 0 is too C-ish. Please use nullptr. Also this needs comment because it is not obvious what this member is. What is Highest? |
Strictly speaking the ABI doesn't require the .ARM.exidx to be terminated by a sentinel, but without one it does mean that the address range of the last entry would only be terminated by the end of the address space. Until recently libunwind depended on the presence of a sentinel.