Skip to content

Commit

Permalink
[ELF][RISCV] Add TLSDESC relaxation.
Browse files Browse the repository at this point in the history
Signed-off-by: Tatsuyuki Ishi <[email protected]>
  • Loading branch information
ishitatsuyuki committed Aug 7, 2023
1 parent dd05e00 commit 18d911c
Showing 1 changed file with 70 additions and 7 deletions.
77 changes: 70 additions & 7 deletions elf/arch-riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -462,24 +462,48 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
break;
}
case R_RISCV_TLSDESC_HI20: {
u64 desc = sym.get_tlsdesc_addr(ctx);
write_utype(loc, desc + A - P);
if (removed_bytes == 0) {
u64 desc = sym.get_tlsdesc_addr(ctx);
write_utype(loc, desc + A - P);
}
break;
}
case R_RISCV_TLSDESC_LOAD_LO12:
case R_RISCV_TLSDESC_ADD_LO12: {
i64 idx2 = find_paired_reloc();
const ElfRel<E> &rel2 = rels[idx2];
Symbol<E> &sym2 = *file.symbols[rel2.r_sym];

u64 S = sym2.get_addr(ctx);
u64 A = rel2.r_addend;
u64 P = get_addr() + rel2.r_offset - get_r_delta(idx2);
u64 desc = sym2.get_tlsdesc_addr(ctx);
write_itype(loc, desc + A - P);
if (sym2.has_tlsdesc(ctx)) {
u64 desc = sym2.get_tlsdesc_addr(ctx);
write_itype(loc, desc + A - P);
} else {
if (removed_bytes == 0) {
assert(rel.r_type == R_RISCV_TLSDESC_ADD_LO12);
*(ul32 *)loc = 0x537; // lui a0,<hi20>
write_utype(loc, S + A - ctx.tp_addr);
}
}
break;
}
case R_RISCV_TLSDESC_CALL:
case R_RISCV_TLSDESC_CALL: {
i64 idx2 = find_paired_reloc();
const ElfRel<E> &rel2 = rels[idx2];
Symbol<E> &sym2 = *file.symbols[rel2.r_sym];
u64 S = sym2.get_addr(ctx);
u64 A = rel2.r_addend;
if (!sym2.has_tlsdesc(ctx)) {
u64 val = S + A - ctx.tp_addr;
if (sign_extend(val, 11) == val)
*(ul32 *)loc = 0x513; // addi a0,zero,<lo12>
else
*(ul32 *)loc = 0x50513; // addi a0,a0,<lo12>
write_itype(loc, val);
}
break;
}
case R_RISCV_ADD8:
loc += S + A;
break;
Expand Down Expand Up @@ -716,7 +740,8 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
sym.flags |= NEEDS_TLSGD;
break;
case R_RISCV_TLSDESC_HI20:
sym.flags |= NEEDS_TLSDESC;
if (!relax_tlsdesc(ctx, sym))
sym.flags |= NEEDS_TLSDESC;
break;
case R_RISCV_32_PCREL:
scan_pcrel(ctx, sym, rel);
Expand Down Expand Up @@ -802,6 +827,21 @@ static void shrink_section(Context<E> &ctx, InputSection<E> &isec, bool use_rvc)
Symbol<E> &sym = *isec.file.symbols[r.r_sym];
isec.extra.r_deltas[i] = delta;

auto find_paired_reloc = [&] {
if (sym.value <= r.r_offset) {
for (i64 j = i - 1; j >= 0; j--)
if (is_paired_reloc_leader(rels[j].r_type) && sym.value == rels[j].r_offset)
return j;
}
if (sym.value >= r.r_offset) {
for (i64 j = i + 1; j < rels.size(); j++)
if (is_paired_reloc_leader(rels[j].r_type) && sym.value == rels[j].r_offset)
return j;
}

Fatal(ctx) << isec << ": paired relocation is missing: " << i;
};

// Handling R_RISCV_ALIGN is mandatory.
//
// R_RISCV_ALIGN refers to NOP instructions. We need to eliminate some
Expand Down Expand Up @@ -889,6 +929,29 @@ static void shrink_section(Context<E> &ctx, InputSection<E> &isec, bool use_rvc)
sign_extend(val, 11) == val)
delta += 4;
break;
case R_RISCV_TLSDESC_HI20:
if (!sym.has_tlsdesc(ctx))
delta += 4;
break;
case R_RISCV_TLSDESC_LOAD_LO12: {
i64 idx2 = find_paired_reloc();
const ElfRel<E> &rel2 = rels[idx2];
Symbol<E> &sym2 = *isec.file.symbols[rel2.r_sym];
if (!sym2.has_tlsdesc(ctx))
delta += 4;
break;
}
case R_RISCV_TLSDESC_ADD_LO12: {
i64 idx2 = find_paired_reloc();
const ElfRel<E> &rel2 = rels[idx2];
Symbol<E> &sym2 = *isec.file.symbols[rel2.r_sym];
if (!sym2.has_tlsdesc(ctx)) {
if (i64 val = sym2.get_addr(ctx) + rel2.r_addend - ctx.tp_addr;
sign_extend(val, 11) == val)
delta += 4;
}
break;
}
}
}

Expand Down

0 comments on commit 18d911c

Please sign in to comment.