diff options
author | mengqinggang <mengqinggang@loongson.cn> | 2023-07-15 17:17:12 +0800 |
---|---|---|
committer | liuzhensong <liuzhensong@loongson.cn> | 2023-07-24 11:22:42 +0800 |
commit | 378535f277b31e28f74cc65df6876c616beb04b4 (patch) | |
tree | 1e69f4f0e61732e392ec683efe59fb1ab0d30046 | |
parent | 5cbe549257b0aed1b615714e74bb6a3f066f3253 (diff) | |
download | gdb-378535f277b31e28f74cc65df6876c616beb04b4.zip gdb-378535f277b31e28f74cc65df6876c616beb04b4.tar.gz gdb-378535f277b31e28f74cc65df6876c616beb04b4.tar.bz2 |
LoongArch: Fix instruction immediate bug caused by sign-extend
For extreme code mode, the instruction sequences is
pcalau12i $t0, hi20
addi.d $t1, $zero, lo12
lu32i.d $t1, lo20
lu52i.d $t1, hi12
add.d $t1, $t0, $t1
If lo12 > 0x7ff, hi20 need to add 0x1, lo20 need to sub 0x1.
If hi20 > 0x7ffff, lo20 need to add 0x1.
bfd/ChangeLog:
* elfnn-loongarch.c (RELOCATE_CALC_PC32_HI20): Redefined.
(RELOCATE_CALC_PC64_HI32): Redefined.
-rw-r--r-- | bfd/elfnn-loongarch.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index d3d8419..e9c408b 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -2284,26 +2284,65 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info, return fatal; } +/* If lo12 immediate > 0x7ff, because sign-extend caused by addi.d/ld.d, + hi20 immediate need to add 0x1. + For example: pc 0x120000000, symbol 0x120000812 + lo12 immediate is 0x812, 0x120000812 & 0xfff = 0x812 + hi20 immediate is 1, because lo12 imm > 0x7ff, symbol need to add 0x1000 + (((0x120000812 + 0x1000) & ~0xfff) - (0x120000000 & ~0xfff)) >> 12 = 0x1 + + At run: + pcalau12i $t0, hi20 (0x1) + $t0 = 0x120000000 + (0x1 << 12) = 0x120001000 + addi.d $t0, $t0, lo12 (0x812) + $t0 = 0x120001000 + 0xfffffffffffff812 (-(0x1000 - 0x812) = -0x7ee) + = 0x120001000 - 0x7ee (0x1000 - 0x7ee = 0x812) + = 0x120000812 + Without hi20 add 0x1000, the result 0x120000000 - 0x7ee = 0x11ffff812 is + error. + 0x1000 + sign-extend-to64(0x8xx) = 0x8xx. */ #define RELOCATE_CALC_PC32_HI20(relocation, pc) \ ({ \ bfd_vma __lo = (relocation) & ((bfd_vma)0xfff); \ - pc = pc & (~(bfd_vma)0xfff); \ + relocation = (relocation & ~(bfd_vma)0xfff) \ + - (pc & ~(bfd_vma)0xfff); \ if (__lo > 0x7ff) \ - { \ relocation += 0x1000; \ - } \ - relocation &= ~(bfd_vma)0xfff; \ - relocation -= pc; \ }) +/* For example: pc is 0x11000010000100, symbol is 0x1812348ffff812 + offset = (0x1812348ffff812 & ~0xfff) - (0x11000010000100 & ~0xfff) + = 0x712347ffff000 + lo12: 0x1812348ffff812 & 0xfff = 0x812 + hi20: 0x7ffff + 0x1(lo12 > 0x7ff) = 0x80000 + lo20: 0x71234 - 0x1(lo12 > 0x7ff) + 0x1(hi20 > 0x7ffff) + hi12: 0x0 + + pcalau12i $t1, hi20 (0x80000) + $t1 = 0x11000010000100 + sign-extend(0x80000 << 12) + = 0x11000010000100 + 0xffffffff80000000 + = 0x10ffff90000000 + addi.d $t0, $zero, lo12 (0x812) + $t0 = 0xfffffffffffff812 (if lo12 > 0x7ff, because sign-extend, + lo20 need to sub 0x1) + lu32i.d $t0, lo12 (0x71234) + $t0 = {0x71234, 0xfffff812} + = 0x71234fffff812 + lu52i.d $t0, hi12 (0x0) + $t0 = {0x0, 0x71234fffff812} + = 0x71234fffff812 + add.d $t1, $t1, $t0 + $t1 = 0x10ffff90000000 + 0x71234fffff812 + = 0x1812348ffff812. */ #define RELOCATE_CALC_PC64_HI32(relocation, pc) \ ({ \ - bfd_vma __lo = (relocation) & ((bfd_vma)0xfff); \ + bfd_vma __lo = (relocation & (bfd_vma)0xfff); \ + relocation = (relocation & ~(bfd_vma)0xfff) \ + - (pc & ~(bfd_vma)0xfff); \ if (__lo > 0x7ff) \ - { \ - relocation -= 0x100000000; \ - } \ - relocation -= (pc & ~(bfd_vma)0xffffffff); \ + relocation += (0x1000 - 0x100000000); \ + if (relocation & 0x80000000) \ + relocation += 0x100000000; \ }) static int |