Skip to content

[ELF] Handle relocations in synthetic .eh_frame with a non-zero offset within the output section #65966

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lld/ELF/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,8 @@ 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 *ehIn = dyn_cast<EhInputSection>(&sec))
secAddr += ehIn->getParent()->outSecOff;
AArch64Relaxer relaxer(sec.relocs());
for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) {
const Relocation &rel = sec.relocs()[i];
Expand Down
2 changes: 2 additions & 0 deletions lld/ELF/Arch/PPC64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1563,6 +1563,8 @@ void PPC64::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 *ehIn = dyn_cast<EhInputSection>(&sec))
secAddr += ehIn->getParent()->outSecOff;
uint64_t lastPPCRelaxedRelocOff = -1;
for (const Relocation &rel : sec.relocs()) {
uint8_t *loc = buf + rel.offset;
Expand Down
2 changes: 2 additions & 0 deletions lld/ELF/Arch/X86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,8 @@ void X86_64::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 *ehIn = dyn_cast<EhInputSection>(&sec))
secAddr += ehIn->getParent()->outSecOff;
for (const Relocation &rel : sec.relocs()) {
if (rel.expr == R_NONE) // See deleteFallThruJmpInsn
continue;
Expand Down
5 changes: 3 additions & 2 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,13 +583,14 @@ static uint64_t readFdeAddr(uint8_t *buf, int size) {
uint64_t EhFrameSection::getFdePc(uint8_t *buf, size_t fdeOff,
uint8_t enc) const {
// The starting address to which this FDE applies is
// stored at FDE + 8 byte.
// stored at FDE + 8 byte. And this offset is within
// the .eh_frame section.
size_t off = fdeOff + 8;
uint64_t addr = readFdeAddr(buf + off, enc & 0xf);
if ((enc & 0x70) == DW_EH_PE_absptr)
return addr;
if ((enc & 0x70) == DW_EH_PE_pcrel)
return addr + getParent()->addr + off;
return addr + getParent()->addr + off + outSecOff;
fatal("unknown FDE size relative encoding");
}

Expand Down
2 changes: 2 additions & 0 deletions lld/ELF/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ void TargetInfo::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 *ehIn = dyn_cast<EhInputSection>(&sec))
secAddr += ehIn->getParent()->outSecOff;
for (const Relocation &rel : sec.relocs()) {
uint8_t *loc = buf + rel.offset;
const uint64_t val = SignExtend64(
Expand Down
53 changes: 53 additions & 0 deletions lld/test/ELF/eh-frame-nonzero-offset-aarch64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// REQUIRES: aarch64
// RUN: rm -rf %t && split-file %s %t && cd %t

// RUN: llvm-mc -filetype=obj -triple=aarch64 a.s -o a.o
// RUN: ld.lld a.o -T eh-frame-non-zero-offset.t -o non-zero
// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame non-zero | FileCheck --check-prefix=NONZERO %s
// RUN: ld.lld a.o -T eh-frame-zero-offset.t -o zero
// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame zero | FileCheck --check-prefix=ZERO %s

// NONZERO: {{[0-9]+}}: 0000000000000088 {{.*}} __eh_frame_start
// NONZERO-NEXT: {{[0-9]+}}: 00000000000000b4 {{.*}} __eh_frame_end

// NONZERO: 0x00000088 10000000 00000000 017a5200 017c1e01
// NONZERO-NEXT: 0x00000098 1b0c1f00 10000000 18000000 5cffffff
// NONZERO-NEXT: 0x000000a8 04000000 00000000 00000000

// ZERO: {{[0-9]+}}: 0000000000000008 {{.*}} __eh_frame_start
// ZERO-NEXT: {{[0-9]+}}: 0000000000000034 {{.*}} __eh_frame_end

// ZERO: 0x00000008 10000000 00000000 017a5200 017c1e01
// ZERO-NEXT: 0x00000018 1b0c1f00 10000000 18000000 dcffffff
// ZERO-NEXT: 0x00000028 04000000 00000000 00000000

//--- eh-frame-non-zero-offset.t
SECTIONS {
.text : { *(.text .text.*) }
.eh_frame : {
/* Padding within .eh_frame */
. += 128;
__eh_frame_start = .;
*(.eh_frame) ;
__eh_frame_end = .;
}
}

//--- eh-frame-zero-offset.t
SECTIONS {
.text : { *(.text .text.*) }
.eh_frame : {
__eh_frame_start = .;
*(.eh_frame) ;
__eh_frame_end = .;
}
}

//--- a.s
.section .text.01, "ax",%progbits
.global f1
.type f1, %function
f1:
.cfi_startproc
.space 4
.cfi_endproc
54 changes: 54 additions & 0 deletions lld/test/ELF/eh-frame-nonzero-offset-arm.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// REQUIRES: arm
// RUN: rm -rf %t && split-file %s %t && cd %t

// RUN: llvm-mc -filetype=obj -triple=arm a.s -o a.o
// RUN: ld.lld a.o -T eh-frame-non-zero-offset.t -o non-zero
// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame non-zero | FileCheck --check-prefix=NONZERO %s
// RUN: ld.lld a.o -T eh-frame-zero-offset.t -o zero
// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame zero | FileCheck --check-prefix=ZERO %s

// NONZERO: {{[0-9]+}}: 00000084 {{.*}} __eh_frame_start
// NONZERO-NEXT: {{[0-9]+}}: 000000b0 {{.*}} __eh_frame_end

// NONZERO: 0x00000084 10000000 00000000 017a5200 017c0e01
// NONZERO-NEXT: 0x00000094 1b0c0d00 10000000 18000000 60ffffff
// NONZERO-NEXT: 0x000000a4 04000000 00000000 00000000

// ZERO: {{[0-9]+}}: 00000004 {{.*}} __eh_frame_start
// ZERO-NEXT: {{[0-9]+}}: 00000030 {{.*}} __eh_frame_end

// ZERO: 0x00000004 10000000 00000000 017a5200 017c0e01
// ZERO-NEXT: 0x00000014 1b0c0d00 10000000 18000000 e0ffffff
// ZERO-NEXT: 0x00000024 04000000 00000000 00000000

//--- eh-frame-non-zero-offset.t
SECTIONS {
.text : { *(.text .text.*) }
.eh_frame : {
/* Padding within .eh_frame */
. += 128;
__eh_frame_start = .;
*(.eh_frame) ;
__eh_frame_end = .;
}
}

//--- eh-frame-zero-offset.t
SECTIONS {
.text : { *(.text .text.*) }
.eh_frame : {
__eh_frame_start = .;
*(.eh_frame) ;
__eh_frame_end = .;
}
}

//--- a.s
.section .text.01, "ax",%progbits
.global f1
.type f1, %function
f1:
.cfi_startproc
.cfi_sections .eh_frame
.space 4
.cfi_endproc
53 changes: 53 additions & 0 deletions lld/test/ELF/eh-frame-nonzero-offset-ppc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// REQUIRES: ppc
// RUN: rm -rf %t && split-file %s %t && cd %t

// RUN: llvm-mc -filetype=obj -triple=ppc64le a.s -o a.o
// RUN: ld.lld a.o -T eh-frame-non-zero-offset.t -o non-zero
// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame non-zero | FileCheck --check-prefix=NONZERO %s
// RUN: ld.lld a.o -T eh-frame-zero-offset.t -o zero
// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame zero | FileCheck --check-prefix=ZERO %s

// NONZERO: {{[0-9]+}}: 0000000000000088 {{.*}} __eh_frame_start
// NONZERO-NEXT: {{[0-9]+}}: 00000000000000b4 {{.*}} __eh_frame_end

// NONZERO: 0x00000088 10000000 00000000 017a5200 04784101
// NONZERO-NEXT: 0x00000098 1b0c0100 10000000 18000000 5cffffff
// NONZERO-NEXT: 0x000000a8 04000000 00000000 00000000

// ZERO: {{[0-9]+}}: 0000000000000008 {{.*}} __eh_frame_start
// ZERO-NEXT: {{[0-9]+}}: 0000000000000034 {{.*}} __eh_frame_end

// ZERO: 0x00000008 10000000 00000000 017a5200 04784101
// ZERO-NEXT: 0x00000018 1b0c0100 10000000 18000000 dcffffff
// ZERO-NEXT: 0x00000028 04000000 00000000 00000000

//--- eh-frame-non-zero-offset.t
SECTIONS {
.text : { *(.text .text.*) }
.eh_frame : {
/* Padding within .eh_frame */
. += 128;
__eh_frame_start = .;
*(.eh_frame) ;
__eh_frame_end = .;
}
}

//--- eh-frame-zero-offset.t
SECTIONS {
.text : { *(.text .text.*) }
.eh_frame : {
__eh_frame_start = .;
*(.eh_frame) ;
__eh_frame_end = .;
}
}

//--- a.s
.section .text.01, "ax",%progbits
.global f1
.type f1, %function
f1:
.cfi_startproc
.space 4
.cfi_endproc
55 changes: 55 additions & 0 deletions lld/test/ELF/eh-frame-nonzero-offset-x86.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// REQUIRES: x86
// RUN: rm -rf %t && split-file %s %t && cd %t

// RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
// RUN: ld.lld a.o -T eh-frame-non-zero-offset.t -o non-zero
// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame non-zero | FileCheck --check-prefix=NONZERO %s
// RUN: ld.lld a.o -T eh-frame-zero-offset.t -o zero
// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame zero | FileCheck --check-prefix=ZERO %s

// NONZERO: {{[0-9]+}}: 0000000000000088 {{.*}} __eh_frame_start
// NONZERO-NEXT: {{[0-9]+}}: 00000000000000bc {{.*}} __eh_frame_end

// NONZERO: 0x00000088 14000000 00000000 017a5200 01781001
// NONZERO-NEXT: 0x00000098 1b0c0708 90010000 14000000 1c000000
// NONZERO-NEXT: 0x000000a8 58ffffff 04000000 00000000 00000000
// NONZERO-NEXT: 0x000000b8 00000000

// ZERO: {{[0-9]+}}: 0000000000000008 {{.*}} __eh_frame_start
// ZERO-NEXT: {{[0-9]+}}: 000000000000003c {{.*}} __eh_frame_end

// ZERO: 0x00000008 14000000 00000000 017a5200 01781001
// ZERO-NEXT: 0x00000018 1b0c0708 90010000 14000000 1c000000
// ZERO-NEXT: 0x00000028 d8ffffff 04000000 00000000 00000000
// ZERO-NEXT: 0x00000038 00000000

//--- eh-frame-non-zero-offset.t
SECTIONS {
.text : { *(.text .text.*) }
.eh_frame : {
/* Padding within .eh_frame */
. += 128;
__eh_frame_start = .;
*(.eh_frame) ;
__eh_frame_end = .;
}
}

//--- eh-frame-zero-offset.t
SECTIONS {
.text : { *(.text .text.*) }
.eh_frame : {
__eh_frame_start = .;
*(.eh_frame) ;
__eh_frame_end = .;
}
}

//--- a.s
.section .text.01, "ax",%progbits
.global f1
.type f1, %function
f1:
.cfi_startproc
.space 4
.cfi_endproc