Skip to content

Commit b74a771

Browse files
committed
Take r_delta into account when computing distance
1 parent 0124058 commit b74a771

File tree

4 files changed

+9
-17
lines changed

4 files changed

+9
-17
lines changed

src/arch-loongarch.cc

+5-10
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
404404
// pcalau12i $t0, 0
405405
// addi.d $t0, $t0, 0
406406
if (is_relaxable_got_load(ctx, *this, i)) {
407-
i64 dist = compute_distance(ctx, sym, *this, rel);
407+
i64 dist = compute_distance(ctx, sym, rel, P);
408408
if (is_int(dist, 32)) {
409409
u32 rd = get_rd(*(ul32 *)loc);
410410
*(ul32 *)(loc + 4) = 0x02c0'0000 | (rd << 5) | rd; // addi.d
@@ -595,8 +595,6 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
595595
if (sym.has_tlsdesc(ctx) && removed_bytes == 0) {
596596
i64 dist = sym.get_tlsdesc_addr(ctx) + A - P;
597597
if (is_int(dist, 22)) {
598-
// If we can directly materialize the PC-relative address
599-
// with pcaddi, do that.
600598
*(ul32 *)loc = 0x1800'0000 | get_rd(*(ul32 *)loc); // pcaddi
601599
write_j20(loc, dist >> 2);
602600
} else {
@@ -610,8 +608,6 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
610608
} else if (sym.has_gottp(ctx)) {
611609
*(ul32 *)loc = 0x1a00'0004; // pcalau12i $a0, 0
612610
write_j20(loc, hi20(sym.get_gottp_addr(ctx) + A, P));
613-
} else if (i64 val = S + A - ctx.tp_addr; 0 <= val && val < 0x1000) {
614-
*(ul32 *)loc = 0x0340'0000; // nop
615611
} else {
616612
*(ul32 *)loc = 0x1400'0004; // lu12i.w $a0, 0
617613
write_j20(loc, (S + A + 0x800 - ctx.tp_addr) >> 12);
@@ -865,6 +861,7 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec) {
865861
for (i64 i = 0; i < rels.size(); i++) {
866862
const ElfRel<E> &r = rels[i];
867863
Symbol<E> &sym = *isec.file.symbols[r.r_sym];
864+
u64 P = isec.get_addr() + r.r_offset - r_delta;
868865

869866
auto remove = [&](i64 d) {
870867
r_delta += d;
@@ -894,7 +891,6 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec) {
894891
alignment = r.r_addend + 4;
895892
}
896893

897-
u64 P = isec.get_addr() + r.r_offset - r_delta;
898894
u64 desired = align_to(P, alignment);
899895
u64 actual = P + alignment - 4;
900896
if (desired != actual)
@@ -945,7 +941,7 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec) {
945941
rels[i + 2].r_type == R_LARCH_PCALA_LO12 &&
946942
rels[i + 2].r_offset == rels[i].r_offset + 4 &&
947943
rels[i + 3].r_type == R_LARCH_RELAX) {
948-
i64 dist = compute_distance(ctx, sym, isec, r);
944+
i64 dist = compute_distance(ctx, sym, r, P);
949945
u32 insn1 = *(ul32 *)(buf + rels[i].r_offset);
950946
u32 insn2 = *(ul32 *)(buf + rels[i].r_offset + 4);
951947
bool is_addi_d = (insn2 & 0xffc0'0000) == 0x02c0'0000;
@@ -965,7 +961,7 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec) {
965961
//
966962
// If the displacement is PC ± 128 MiB, we can use B or BL instead.
967963
// Note that $zero is $r0 and $ra is $r1.
968-
if (i64 dist = compute_distance(ctx, sym, isec, r);
964+
if (i64 dist = compute_distance(ctx, sym, r, P);
969965
is_int(dist, 28))
970966
if (u32 jirl = *(ul32 *)(buf + rels[i].r_offset + 4);
971967
get_rd(jirl) == 0 || get_rd(jirl) == 1)
@@ -983,13 +979,12 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec) {
983979
//
984980
// pcaddi $t0, <offset>
985981
if (is_relaxable_got_load(ctx, isec, i))
986-
if (i64 dist = compute_distance(ctx, sym, isec, r);
982+
if (i64 dist = compute_distance(ctx, sym, r, P);
987983
is_int(dist, 22))
988984
remove(4);
989985
break;
990986
case R_LARCH_TLS_DESC_PC_HI20:
991987
if (sym.has_tlsdesc(ctx)) {
992-
u64 P = isec.get_addr() + r.r_offset;
993988
i64 dist = sym.get_tlsdesc_addr(ctx) + r.r_addend - P;
994989
if (is_int(dist, 22))
995990
remove(4);

src/arch-riscv.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,7 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec) {
854854
for (i64 i = 0; i < rels.size(); i++) {
855855
const ElfRel<E> &r = rels[i];
856856
Symbol<E> &sym = *isec.file.symbols[r.r_sym];
857+
u64 P = isec.get_addr() + r.r_offset - r_delta;
857858

858859
auto remove = [&](i64 d) {
859860
r_delta += d;
@@ -868,7 +869,6 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec) {
868869
if (r.r_type == R_RISCV_ALIGN) {
869870
// The total bytes of NOPs is stored to r_addend, so the next
870871
// instruction is r_addend away.
871-
u64 P = isec.get_addr() + r.r_offset - r_delta;
872872
u64 desired = align_to(P, bit_ceil(r.r_addend));
873873
u64 actual = P + r.r_addend;
874874
if (desired != actual)
@@ -895,7 +895,7 @@ void shrink_section(Context<E> &ctx, InputSection<E> &isec) {
895895
// These relocations refer to an AUIPC + JALR instruction pair to
896896
// allow to jump to anywhere in PC ± 2 GiB. If the jump target is
897897
// close enough to PC, we can use C.J, C.JAL or JAL instead.
898-
i64 dist = compute_distance(ctx, sym, isec, r);
898+
i64 dist = compute_distance(ctx, sym, r, P);
899899
if (dist & 1)
900900
break;
901901

src/mold.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -1598,8 +1598,7 @@ template <typename E>
15981598
i64 get_r_delta(InputSection<E> &isec, u64 offset);
15991599

16001600
template <typename E>
1601-
i64 compute_distance(Context<E> &ctx, Symbol<E> &sym,
1602-
InputSection<E> &isec, const ElfRel<E> &rel);
1601+
i64 compute_distance(Context<E> &ctx, Symbol<E> &sym, const ElfRel<E> &rel, u64 P);
16031602

16041603
//
16051604
// gc-sections.cc

src/shrink-sections.cc

+1-3
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ void shrink_sections(Context<E> &ctx) {
112112

113113
// Returns the distance between a relocated place and a symbol.
114114
template <>
115-
i64 compute_distance(Context<E> &ctx, Symbol<E> &sym,
116-
InputSection<E> &isec, const ElfRel<E> &rel) {
115+
i64 compute_distance(Context<E> &ctx, Symbol<E> &sym, const ElfRel<E> &rel, u64 P) {
117116
// We handle absolute symbols as if they were infinitely far away
118117
// because `shrink_section` may increase a distance between a branch
119118
// instruction and an absolute symbol. Branching to an absolute
@@ -128,7 +127,6 @@ i64 compute_distance(Context<E> &ctx, Symbol<E> &sym,
128127
// Compute a distance between the relocated place and the symbol.
129128
i64 S = sym.get_addr(ctx);
130129
i64 A = rel.r_addend;
131-
i64 P = isec.get_addr() + rel.r_offset;
132130
return S + A - P;
133131
}
134132

0 commit comments

Comments
 (0)