[clang] [LLD][AARCH64] lld incorrectly handles .eh_frame when it has a non-zero offset within its output section. (PR #65966)

Peter Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 11 09:16:59 PDT 2023


================
@@ -770,6 +770,9 @@ void AArch64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
   uint64_t secAddr = sec.getOutputSection()->addr;
   if (auto *s = dyn_cast<InputSection>(&sec))
     secAddr += s->outSecOff;
+  else if (auto *eh = dyn_cast<EhInputSection>(&sec))
----------------
smithp35 wrote:

I don't think this problem specific to AArch64? It would also affect the other targets that use .eh_frame such as x86_64.

As I understand it this was triggered by the Picolibc linker script (https://github.com/picolibc/picolibc/blob/main/picolibc.ld.in) with extract:
```
	.except_ordered : {
		*(.gcc_except_table *.gcc_except_table.*)
		KEEP (*(.eh_frame .eh_frame.*))
		*(.ARM.extab* .gnu.linkonce.armextab.*)
	} >flash AT>flash :text
```
Which has the .eh_frame sections after .gcc_except_table.

I made a failing test case for x86_64 by editing the output of GNU ld's --verbose and adding a dummy QUAD statement. I've not included the whole ld --verbose output as it is rather long.
```
 /* Insert QUAD(0) to make .eh_frame start at non 0 offset within ouptut section */
 .eh_frame       : ONLY_IF_RO { QUAD(0); KEEP (*(.eh_frame)) *(.eh_frame.*) }
```
With the simple test program
```
#include <stdio.h>

int main(void) {
  try {
    throw 55;
  }
  catch (int i) { printf("Caught int %d\n", i); }
  catch (...) { printf("Caught generic\n"); }
  return 0;
}
```
With results:
```
clang++ -fuse-ld=bfd throw.cpp -o throw.exe -Wl,--script=ld.script
./throw.exe
Caught int 55
clang++ -fuse-ld=lld throw.cpp -o throw.exe -Wl,--script=ld.script
./throw.exe
[1]    444896 abort (core dumped)  ./throw.exe
```


https://github.com/llvm/llvm-project/pull/65966


More information about the cfe-commits mailing list