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

2023-09-11 Thread via cfe-commits

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

>From 7cd4fe122a329d29023f978991baa486266a32f3 Mon Sep 17 00:00:00 2001
From: Simi Pallipurath 
Date: Mon, 11 Sep 2023 14:42:27 +0100
Subject: [PATCH 1/2] [LLD][AARCH64] lld incorrectly handles .eh_frame when it
 has a non-zero offset within its output section.

When the .eh_frame section is placed at a non-zero
offset within its output section, the relocation
value within .eh_frame are computed incorrectly.

We had similar issue in AArch32 and it has been
fixed already in https://reviews.llvm.org/D148033.

While applying the relocation using S+A-P, the value
of P (the location of the relocation) is getting wrong.
P is:
  P = SecAddr + rel.offset, But SecAddr points to the
starting address of the outputsection rather than the
starting address of the eh frame section within that
output section.
---
 lld/ELF/Arch/AArch64.cpp   |  3 ++
 lld/test/ELF/eh-frame-nonzero-offset.s | 55 ++
 2 files changed, 58 insertions(+)
 create mode 100644 lld/test/ELF/eh-frame-nonzero-offset.s

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 174a0a3624f7765..fd0ef28737042b4 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -1081,3 +1081,6 @@ void lld::elf::createTaggedSymbols(const 
SmallVector &files) {
 symbol->setIsTagged(true);
   }
 }
+  else if (auto *eh = dyn_cast(&sec))
+if (InputSection *isec = eh->getParent())
+  secAddr += isec->outSecOff;
diff --git a/lld/test/ELF/eh-frame-nonzero-offset.s 
b/lld/test/ELF/eh-frame-nonzero-offset.s
new file mode 100644
index 000..ef086fcf670d81b
--- /dev/null
+++ b/lld/test/ELF/eh-frame-nonzero-offset.s
@@ -0,0 +1,55 @@
+// REQUIRES: aarch64
+// RUN: rm -rf %t && split-file %s %t
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64 %t/a.s -o %t/a.o
+// RUN: ld.lld %t/a.o -T %t/eh-frame-non-zero-offset.t -o %t/non-zero
+// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame 
%t/non-zero | FileCheck --check-prefix=NONZERO %s
+// RUN: ld.lld %t/a.o -T %t/eh-frame-zero-offset.t -o %t/zero
+// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame %t/zero 
| FileCheck --check-prefix=ZERO %s
+
+// NONZERO:  {{[0-9]+}}: 0080 {{.*}} __eh_frame_start
+// NONZERO-NEXT: {{[0-9]+}}: 00ac {{.*}} __eh_frame_end
+
+// NONZERO:  0x0078   1000 
+// NONZERO-NEXT: 0x0088 017a5200 017c1e01 1b0c1f00 1000
+// NONZERO-NEXT: 0x0098 1800 64ff 0800 
+// NONZERO-NEXT: 0x00a8 
+
+// ZERO:  {{[0-9]+}}: 0080 {{.*}} __eh_frame_start
+// ZERO-NEXT: {{[0-9]+}}: 00ac {{.*}} __eh_frame_end
+
+// ZERO:  0x0080 1000  017a5200 017c1e01
+// ZERO-NEXT: 0x0090 1b0c1f00 1000 1800 64ff
+// ZERO-NEXT: 0x00a0 0800  
+
+//--- eh-frame-non-zero-offset.t
+SECTIONS {
+  .text : { *(.text .text.*) }
+  .eh_frame : {
+  /* Alignment padding within .eh_frame */
+  . = ALIGN(128);
+  __eh_frame_start = .;
+  *(.eh_frame .eh_frame.*) ;
+  __eh_frame_end = .;
+  }
+}
+
+//--- eh-frame-zero-offset.t
+SECTIONS {
+  .text : { *(.text .text.*) }
+  .eh_frame : ALIGN(128) {
+  __eh_frame_start = .;
+  *(.eh_frame .eh_frame.*) ;
+  __eh_frame_end = .;
+  }
+}
+
+//--- a.s
+.section .text.01, "ax",%progbits
+.global f1
+.type f1, %function
+f1:
+.cfi_startproc
+   nop
+   nop
+.cfi_endproc

>From 31e116847f013c2c9301bb1868fa7a10af9bdf8b Mon Sep 17 00:00:00 2001
From: Simi Pallipurath 
Date: Mon, 11 Sep 2023 14:42:27 +0100
Subject: [PATCH 2/2] [LLD][AARCH64] lld incorrectly handles .eh_frame when it
 has a non-zero offset within its output section.

When the .eh_frame section is placed at a non-zero
offset within its output section, the relocation
value within .eh_frame are computed incorrectly.

We had similar issue in AArch32 and it has been
fixed already in https://reviews.llvm.org/D148033.

While applying the relocation using S+A-P, the value
of P (the location of the relocation) is getting wrong.
P is:
  P = SecAddr + rel.offset, But SecAddr points to the
starting address of the outputsection rather than the
starting address of the eh frame section within that
output section.
---
 lld/ELF/Arch/AArch64.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index fd0ef28737042b4..411c0a046bd7c58 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -770,6 +770,9 @@ void AArch64::relocateAlloc(InputSectionBase &sec, uint8_t 
*buf) const {
   uint64_t secAddr = sec.getOutputSection()->addr;
   if (auto *s = dyn_cast(&sec))
 secAddr += s->outSecOff;
+  else if (auto *eh = dyn_cast(&sec))
+if (InputSection *isec = eh->getParent())
+  secAddr += isec->outSecOff;
   AArch64Relaxer relaxer(sec.relocs());
   for (size_t i = 0, size = sec.relocs().size(); i != 

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

2023-09-11 Thread via cfe-commits

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

>From 7cd4fe122a329d29023f978991baa486266a32f3 Mon Sep 17 00:00:00 2001
From: Simi Pallipurath 
Date: Mon, 11 Sep 2023 14:42:27 +0100
Subject: [PATCH 1/3] [LLD][AARCH64] lld incorrectly handles .eh_frame when it
 has a non-zero offset within its output section.

When the .eh_frame section is placed at a non-zero
offset within its output section, the relocation
value within .eh_frame are computed incorrectly.

We had similar issue in AArch32 and it has been
fixed already in https://reviews.llvm.org/D148033.

While applying the relocation using S+A-P, the value
of P (the location of the relocation) is getting wrong.
P is:
  P = SecAddr + rel.offset, But SecAddr points to the
starting address of the outputsection rather than the
starting address of the eh frame section within that
output section.
---
 lld/ELF/Arch/AArch64.cpp   |  3 ++
 lld/test/ELF/eh-frame-nonzero-offset.s | 55 ++
 2 files changed, 58 insertions(+)
 create mode 100644 lld/test/ELF/eh-frame-nonzero-offset.s

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 174a0a3624f7765..fd0ef28737042b4 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -1081,3 +1081,6 @@ void lld::elf::createTaggedSymbols(const 
SmallVector &files) {
 symbol->setIsTagged(true);
   }
 }
+  else if (auto *eh = dyn_cast(&sec))
+if (InputSection *isec = eh->getParent())
+  secAddr += isec->outSecOff;
diff --git a/lld/test/ELF/eh-frame-nonzero-offset.s 
b/lld/test/ELF/eh-frame-nonzero-offset.s
new file mode 100644
index 000..ef086fcf670d81b
--- /dev/null
+++ b/lld/test/ELF/eh-frame-nonzero-offset.s
@@ -0,0 +1,55 @@
+// REQUIRES: aarch64
+// RUN: rm -rf %t && split-file %s %t
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64 %t/a.s -o %t/a.o
+// RUN: ld.lld %t/a.o -T %t/eh-frame-non-zero-offset.t -o %t/non-zero
+// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame 
%t/non-zero | FileCheck --check-prefix=NONZERO %s
+// RUN: ld.lld %t/a.o -T %t/eh-frame-zero-offset.t -o %t/zero
+// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame %t/zero 
| FileCheck --check-prefix=ZERO %s
+
+// NONZERO:  {{[0-9]+}}: 0080 {{.*}} __eh_frame_start
+// NONZERO-NEXT: {{[0-9]+}}: 00ac {{.*}} __eh_frame_end
+
+// NONZERO:  0x0078   1000 
+// NONZERO-NEXT: 0x0088 017a5200 017c1e01 1b0c1f00 1000
+// NONZERO-NEXT: 0x0098 1800 64ff 0800 
+// NONZERO-NEXT: 0x00a8 
+
+// ZERO:  {{[0-9]+}}: 0080 {{.*}} __eh_frame_start
+// ZERO-NEXT: {{[0-9]+}}: 00ac {{.*}} __eh_frame_end
+
+// ZERO:  0x0080 1000  017a5200 017c1e01
+// ZERO-NEXT: 0x0090 1b0c1f00 1000 1800 64ff
+// ZERO-NEXT: 0x00a0 0800  
+
+//--- eh-frame-non-zero-offset.t
+SECTIONS {
+  .text : { *(.text .text.*) }
+  .eh_frame : {
+  /* Alignment padding within .eh_frame */
+  . = ALIGN(128);
+  __eh_frame_start = .;
+  *(.eh_frame .eh_frame.*) ;
+  __eh_frame_end = .;
+  }
+}
+
+//--- eh-frame-zero-offset.t
+SECTIONS {
+  .text : { *(.text .text.*) }
+  .eh_frame : ALIGN(128) {
+  __eh_frame_start = .;
+  *(.eh_frame .eh_frame.*) ;
+  __eh_frame_end = .;
+  }
+}
+
+//--- a.s
+.section .text.01, "ax",%progbits
+.global f1
+.type f1, %function
+f1:
+.cfi_startproc
+   nop
+   nop
+.cfi_endproc

>From 31e116847f013c2c9301bb1868fa7a10af9bdf8b Mon Sep 17 00:00:00 2001
From: Simi Pallipurath 
Date: Mon, 11 Sep 2023 14:42:27 +0100
Subject: [PATCH 2/3] [LLD][AARCH64] lld incorrectly handles .eh_frame when it
 has a non-zero offset within its output section.

When the .eh_frame section is placed at a non-zero
offset within its output section, the relocation
value within .eh_frame are computed incorrectly.

We had similar issue in AArch32 and it has been
fixed already in https://reviews.llvm.org/D148033.

While applying the relocation using S+A-P, the value
of P (the location of the relocation) is getting wrong.
P is:
  P = SecAddr + rel.offset, But SecAddr points to the
starting address of the outputsection rather than the
starting address of the eh frame section within that
output section.
---
 lld/ELF/Arch/AArch64.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index fd0ef28737042b4..411c0a046bd7c58 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -770,6 +770,9 @@ void AArch64::relocateAlloc(InputSectionBase &sec, uint8_t 
*buf) const {
   uint64_t secAddr = sec.getOutputSection()->addr;
   if (auto *s = dyn_cast(&sec))
 secAddr += s->outSecOff;
+  else if (auto *eh = dyn_cast(&sec))
+if (InputSection *isec = eh->getParent())
+  secAddr += isec->outSecOff;
   AArch64Relaxer relaxer(sec.relocs());
   for (size_t i = 0, size = sec.relocs().size(); i != 

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

2023-09-11 Thread via cfe-commits

https://github.com/simpal01 ready_for_review 
https://github.com/llvm/llvm-project/pull/65966
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-09-11 Thread Peter Smith via cfe-commits

https://github.com/smithp35 edited 
https://github.com/llvm/llvm-project/pull/65966
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-09-11 Thread Peter Smith via cfe-commits

https://github.com/smithp35 commented:

This will only fix the problem for AArch64, but it also affects other targets. 
Assuming relocateAlloc is the best place to fix this, then it would need 
applying in all instances of relocateAlloc.

https://github.com/llvm/llvm-project/pull/65966
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-09-11 Thread Peter Smith via cfe-commits


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

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
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-09-11 Thread via cfe-commits


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

simpal01 wrote:

yeah this affects all other targets (might be X86 and PPC as well). 

https://github.com/llvm/llvm-project/pull/65966
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-09-12 Thread via cfe-commits


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

simpal01 wrote:

i could not find the general way of fixing this without modifying 
target->relocateAlloc. 

https://github.com/llvm/llvm-project/pull/65966
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-09-18 Thread via cfe-commits

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

>From eb4d99345cbe9aba6b909ccbc7ce932dcaef3f7d Mon Sep 17 00:00:00 2001
From: Simi Pallipurath 
Date: Mon, 11 Sep 2023 14:42:27 +0100
Subject: [PATCH] [LLD][AARCH64] lld incorrectly handles .eh_frame when it has
 a non-zero offset within its output section.

When the .eh_frame section is placed at a non-zero
offset within its output section, the relocation
value within .eh_frame are computed incorrectly.

We had similar issue in AArch32 and it has been
fixed already in https://reviews.llvm.org/D148033.

While applying the relocation using S+A-P, the value
of P (the location of the relocation) is getting wrong.
P is:
  P = SecAddr + rel.offset, But SecAddr points to the
starting address of the outputsection rather than the
starting address of the eh frame section within that
output section.
---
 lld/ELF/Arch/AArch64.cpp   |  3 ++
 lld/test/ELF/eh-frame-nonzero-offset.s | 55 ++
 2 files changed, 58 insertions(+)
 create mode 100644 lld/test/ELF/eh-frame-nonzero-offset.s

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 174a0a3624f7765..09477141c777948 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -770,6 +770,9 @@ void AArch64::relocateAlloc(InputSectionBase &sec, uint8_t 
*buf) const {
   uint64_t secAddr = sec.getOutputSection()->addr;
   if (auto *s = dyn_cast(&sec))
 secAddr += s->outSecOff;
+  else if (auto *eh = dyn_cast(&sec))
+if (InputSection *isec = eh->getParent())
+  secAddr += isec->outSecOff;
   AArch64Relaxer relaxer(sec.relocs());
   for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) {
 const Relocation &rel = sec.relocs()[i];
diff --git a/lld/test/ELF/eh-frame-nonzero-offset.s 
b/lld/test/ELF/eh-frame-nonzero-offset.s
new file mode 100644
index 000..ef086fcf670d81b
--- /dev/null
+++ b/lld/test/ELF/eh-frame-nonzero-offset.s
@@ -0,0 +1,55 @@
+// REQUIRES: aarch64
+// RUN: rm -rf %t && split-file %s %t
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64 %t/a.s -o %t/a.o
+// RUN: ld.lld %t/a.o -T %t/eh-frame-non-zero-offset.t -o %t/non-zero
+// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame 
%t/non-zero | FileCheck --check-prefix=NONZERO %s
+// RUN: ld.lld %t/a.o -T %t/eh-frame-zero-offset.t -o %t/zero
+// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame %t/zero 
| FileCheck --check-prefix=ZERO %s
+
+// NONZERO:  {{[0-9]+}}: 0080 {{.*}} __eh_frame_start
+// NONZERO-NEXT: {{[0-9]+}}: 00ac {{.*}} __eh_frame_end
+
+// NONZERO:  0x0078   1000 
+// NONZERO-NEXT: 0x0088 017a5200 017c1e01 1b0c1f00 1000
+// NONZERO-NEXT: 0x0098 1800 64ff 0800 
+// NONZERO-NEXT: 0x00a8 
+
+// ZERO:  {{[0-9]+}}: 0080 {{.*}} __eh_frame_start
+// ZERO-NEXT: {{[0-9]+}}: 00ac {{.*}} __eh_frame_end
+
+// ZERO:  0x0080 1000  017a5200 017c1e01
+// ZERO-NEXT: 0x0090 1b0c1f00 1000 1800 64ff
+// ZERO-NEXT: 0x00a0 0800  
+
+//--- eh-frame-non-zero-offset.t
+SECTIONS {
+  .text : { *(.text .text.*) }
+  .eh_frame : {
+  /* Alignment padding within .eh_frame */
+  . = ALIGN(128);
+  __eh_frame_start = .;
+  *(.eh_frame .eh_frame.*) ;
+  __eh_frame_end = .;
+  }
+}
+
+//--- eh-frame-zero-offset.t
+SECTIONS {
+  .text : { *(.text .text.*) }
+  .eh_frame : ALIGN(128) {
+  __eh_frame_start = .;
+  *(.eh_frame .eh_frame.*) ;
+  __eh_frame_end = .;
+  }
+}
+
+//--- a.s
+.section .text.01, "ax",%progbits
+.global f1
+.type f1, %function
+f1:
+.cfi_startproc
+   nop
+   nop
+.cfi_endproc

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits