This is an archive of the discontinued LLVM Phabricator instance.

[LLD][ARM] Handle .ARM.exidx sections at non-zero output sec offset
ClosedPublic

Authored by peter.smith on Apr 11 2023, 10:48 AM.

Details

Summary

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.

Diff Detail

Event Timeline

peter.smith created this revision.Apr 11 2023, 10:48 AM
peter.smith requested review of this revision.Apr 11 2023, 10:48 AM

Update comments, better description of expected results and add missing full stops.

Thanks for the patch. I prefer the current approach than changing PT_ARM_EXIDX to PT_NULL. The code change looks good.

This does not seem to be the case for GNU and LLVM readelf which seems to look for the SHT_ARM_EXIDX section.

Confirmed that they just check the section type SHT_ARM_EXIDX, not the program header type. Perhaps readelf -D -u can be made to check PT_ARM_EXIDX, but the change is likely over-engineering..

lld/ELF/Writer.cpp
2631

Perhaps use if (part.armExidx && p->p_type == PT_ARM_EXIDX). The two conditions are equivalent, but checking part.armExidx is safer in case part.armExidx is null.

lld/test/ELF/arm-exidx-nonzero-offset.s
10

Shall we use llvm-readelf --unwind output as well? The output can be more readable, though it doesn't use the GNU readelf style...

29
42

.exceptions has different alignment than the previous line.

Address review comments:

  • Use part.armExidx instead of config->emachine
  • Tidy up white space in test.
  • Add llvm-readelf --unwind output to test.

I noticed that llvm-readelf --unwind can't decode function names with the Thumb bit set although arm-none-eabi-readelf can. I've used CHECK rather than CHECK-NEXT just in case llvm-readelf --unwind output is improved.

MaskRay accepted this revision.Apr 13 2023, 1:30 PM

Looks great!

Optional: consider adding a note to lld/docs/ReleaseNotes.rst. There are some examples in previous releases, e.g. git show origin/release/15.x:lld/docs/ReleaseNotes.rst

This revision is now accepted and ready to land.Apr 13 2023, 1:30 PM
peter.smith marked 4 inline comments as done.

Add entry in release notes under Fixes.

Herald added a project: Restricted Project. · View Herald TranscriptApr 14 2023, 2:12 AM