Skip to content

Commit

Permalink
Support R_LARCH_CALL36
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Jul 31, 2024
1 parent bf79ae1 commit 2c6f379
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 0 deletions.
30 changes: 30 additions & 0 deletions elf/arch-loongarch.cc
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,20 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
case R_LARCH_64_PCREL:
*(ul64 *)loc = S + A - P;
break;
case R_LARCH_CALL36:
if (removed_bytes == 0) {
write_j20(loc, (S + A - P + 0x20000) >> 18);
write_k16(loc + 4, (S + A - P) >> 2);
} else {
// Rewrite PCADDU18I + JIRL to B or BL
assert(removed_bytes == 4);
if (get_rd(*(ul32 *)(contents.data() + rel.r_offset + 4)) == 0)
*(ul32 *)loc = 0x5000'0000; // B
else
*(ul32 *)loc = 0x5400'0000; // BL
write_k16(loc, (S + A - P) >> 2);
}
break;
case R_LARCH_ADD_ULEB128:
overwrite_uleb(loc, read_uleb(loc) + S + A);
break;
Expand Down Expand Up @@ -626,6 +640,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
break;
case R_LARCH_B26:
case R_LARCH_PCALA_HI20:
case R_LARCH_CALL36:
if (sym.is_imported)
sym.flags |= NEEDS_PLT;
break;
Expand Down Expand Up @@ -792,6 +807,21 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec, bool use_rvc) {
delta += 4;
}
break;
case R_LARCH_CALL36:
// A CALL36 relocation referes to the following instruction pair
// to jump to PC ± 128 GiB.
//
// pcaddu18i $t0, 0 # R_LARCH_CALL36
// jirl $zero/$ra, $t0, 0
//
// If the displacement is PC ± 128 MiB, we can use B or BL instead.
// Note that $zero is $r0 and $ra is $r1.
if (i64 dist = compute_distance(ctx, sym, isec, r);
-(1 << 27) <= dist && dist < (1 << 27))
if (u32 jirl = *(ul32 *)(isec.contents.data() + rels[i].r_offset + 4);
get_rd(jirl) == 0 || get_rd(jirl) == 1)
delta += 4;
break;
}
}

Expand Down
47 changes: 47 additions & 0 deletions test/elf/loongarch64_relax-call36.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/bin/bash
. $(dirname $0)/common.inc

cat <<'EOF' | $CC -o $t/a.o -c -xassembler -
.globl foo, bar
foo:
move $s0, $ra
.reloc ., R_LARCH_CALL36, foo2
.reloc ., R_LARCH_RELAX
pcaddu18i $t0, 0
jirl $ra, $t0, 0
move $ra, $s0
ret
bar:
.reloc ., R_LARCH_CALL36, bar2
.reloc ., R_LARCH_RELAX
pcaddu18i $t0, 0
jirl $zero, $t0, 0
EOF

cat <<EOF | $CC -o $t/b.o -c -xc -
#include <stdio.h>
void foo();
void bar();
void foo2() { printf("foo"); }
void bar2() { printf("bar"); }
int main() {
foo();
bar();
printf("\n");
}
EOF

$CC -B. -o $t/exe1 $t/a.o $t/b.o -Wl,--no-relax
$QEMU $t/exe1 | grep -q foobar

$OBJDUMP -d $t/exe1 > $t/exe1.objdump
grep -A2 '<foo>:' $t/exe1.objdump | grep -wq pcaddu18i
grep -A2 '<bar>:' $t/exe1.objdump | grep -wq pcaddu18i

$CC -B. -o $t/exe2 $t/a.o $t/b.o -Wl,--relax
$QEMU $t/exe2 | grep -q foobar

$OBJDUMP -d $t/exe2 > $t/exe2.objdump
grep -A2 '<foo>:' $t/exe2.objdump | grep -wq bl
grep -A2 '<bar>:' $t/exe2.objdump | grep -wq b
Empty file modified test/elf/loongarch64_relax-pcala-addi.sh
100644 → 100755
Empty file.

0 comments on commit 2c6f379

Please sign in to comment.