Embedded systems that do not use an ELF loader locate the .ARM.exidx exception table via linker defined exidx_start and exidx_end rather than use the PT_ARM_EXIDX program header. This means that some linker scripts such as the picolibc C library's linker script, do not have the .ARM.exidx sections at offset 0 in the OutputSection. For example from https://github.com/picolibc/picolibc/blob/main/picolibc.ld.in#L126:
.except_unordered : { . = ALIGN(8); PROVIDE(__exidx_start = .); *(.ARM.exidx*) PROVIDE(__exidx_end = .); } >flash AT>flash :text
This is within the specification of Arm exception tables, and is handled correctly by ld.bfd. The specification even permits the .ARM.exidx sections to be placed within the .rodata section, but that is very uncommon.
This patch has 2 parts. The first updates the writing of the data of the .ARM.exidx SyntheticSection to account for a non-zero OutputSection offset. The second part makes the PT_ARM_EXIDX program header generation a special case so that it covers only the SyntheticSection and not the parent OutputSection. While not strictly necessary for programs locating the exception tables via the symbols it may cause ELF utilities that locate the exception tables via the PT_ARM_EXIDX program header to fail. This does not seem to be the
case for GNU and LLVM readelf which seems to look for the SHT_ARM_EXIDX section.
An alternative simpler way of handling the PT_ARM_EXIDX is to write a PT_NULL program header if the output section offset of the SyntheticSection is non 0. I don't think that we can remove the program header as the size of the table has already been calculated.
Shall we use llvm-readelf --unwind output as well? The output can be more readable, though it doesn't use the GNU readelf style...