[lld] LLD: Fix getFdePC with sdata2 or sdata4 (PR #92228)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 15 01:45:19 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld
Author: YunQiang Su (wzssyqa)
<details>
<summary>Changes</summary>
LLD uses uint64_t to hold PC value. If an Fde is DW_EH_PE_absptr with data type sdata, getFdePc may return a negtive value and then convert to uint64_t. It will fail to so some add/sub with other address values:
PC offset is too large: 0xffffffff00000040 is expected.
So if Fde is DW_EH_PE_absptr, let's convert its value to uint16_t(sdata2) or uint32_t(sdata4).
We also do similiar things to DW_EH_PE_pcrel: the value of it should be a signed offset, thus, let's convert them to signed values before use them to add with other address values.
Fixes: #<!-- -->88852.
---
Full diff: https://github.com/llvm/llvm-project/pull/92228.diff
3 Files Affected:
- (modified) lld/ELF/SyntheticSections.cpp (+17-4)
- (added) lld/test/ELF/Inputs/mips32-kseg0.lds (+8)
- (modified) lld/test/ELF/mips-eh_frame-pic.s (+5)
``````````diff
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 7b9ada40c0f67..9749e601d8b16 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -612,10 +612,23 @@ uint64_t EhFrameSection::getFdePc(uint8_t *buf, size_t fdeOff,
// 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 + outSecOff;
+ if ((enc & 0x70) == DW_EH_PE_absptr) {
+ if ((enc & 0xf) == DW_EH_PE_sdata2)
+ return (uint64_t)(uint16_t)addr;
+ else if ((enc & 0xf) == DW_EH_PE_sdata4)
+ return (uint64_t)(uint32_t)addr;
+ else
+ return addr;
+ }
+ if ((enc & 0x70) == DW_EH_PE_pcrel) {
+ uint64_t addr_base = getParent()->addr + off + outSecOff;
+ if ((enc & 0xf) == DW_EH_PE_sdata2)
+ return (int16_t)addr + addr_base;
+ else if ((enc & 0xf) == DW_EH_PE_sdata4)
+ return (int32_t)addr + addr_base;
+ else
+ return addr + addr_base;
+ }
fatal("unknown FDE size relative encoding");
}
diff --git a/lld/test/ELF/Inputs/mips32-kseg0.lds b/lld/test/ELF/Inputs/mips32-kseg0.lds
new file mode 100644
index 0000000000000..613194adcca7c
--- /dev/null
+++ b/lld/test/ELF/Inputs/mips32-kseg0.lds
@@ -0,0 +1,8 @@
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+ . = 0x80000000;
+ .text : { *(.text) }
+ .data : { *(.data) }
+ .bss : { *(.bss) }
+}
diff --git a/lld/test/ELF/mips-eh_frame-pic.s b/lld/test/ELF/mips-eh_frame-pic.s
index 79076e74a7e3f..b400114c8b7b7 100644
--- a/lld/test/ELF/mips-eh_frame-pic.s
+++ b/lld/test/ELF/mips-eh_frame-pic.s
@@ -23,15 +23,20 @@
# RUN: llvm-dwarfdump --eh-frame %t-nopic32.o | FileCheck %s --check-prefix=ABS32-EH-FRAME
# RUN: llvm-readobj -r %t-nopic32.o | FileCheck %s --check-prefixes=RELOCS,ABS32-RELOCS
# RUN: not ld.lld -shared %t-nopic32.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=NOPIC32-ERR
+# RUN: ld.lld %t-nopic32.o -T %p/Inputs/mips32-kseg0.lds -eh-frame-hdr -static -o /dev/null 2>&1 \
+# RUN: | FileCheck %s --check-prefix=NOPIC32-ABSPTR
## Note: ld.bfd can link this file because it rewrites the .eh_frame section to use
## relative addressing.
# NOPIC32-ERR: ld.lld: error: relocation R_MIPS_32 cannot be used against local symbol
+# NOPIC32-ABSPTR: cannot find entry symbol __start
## For -fPIC, .eh_frame should contain DW_EH_PE_pcrel | DW_EH_PE_sdata4 values:
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux --position-independent %s -o %t-pic32.o
# RUN: llvm-readobj -r %t-pic32.o | FileCheck %s --check-prefixes=RELOCS,PIC32-RELOCS
# RUN: ld.lld -shared %t-pic32.o -o %t-pic32.so
+# RUN: ld.lld -shared -T %p/Inputs/mips32-kseg0.lds %t-pic32.o -o %t-pic32-kseg0.so
# RUN: llvm-dwarfdump --eh-frame %t-pic32.so | FileCheck %s --check-prefix=PIC32-EH-FRAME
+# RUN: llvm-dwarfdump --eh-frame %t-pic32-kseg0.so | FileCheck %s --check-prefix=PIC32-EH-FRAME
# RELOCS: .rel{{a?}}.eh_frame {
# ABS32-RELOCS-NEXT: 0x1C R_MIPS_32 .text
``````````
</details>
https://github.com/llvm/llvm-project/pull/92228
More information about the llvm-commits
mailing list