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:
Exception Handling for the ARM architecture | http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf |
ELF for the ARM Architecture | http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf |
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 place | action to take for function |
An entry can take one of three forms
PREL31 offset to function | 0x00000001 for special .cantunwind |
PREL31 offset to function | bit 31 set for Inline Table Entry |
PREL31 offset to function | bit 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.
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.