1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-20 17:39:56 +03:00

[ELF][SPARC] Fix more test failures

This commit is contained in:
Rui Ueyama 2022-09-19 17:42:57 +08:00
parent 139aae9444
commit 9dcc70f6ee
8 changed files with 34 additions and 25 deletions

View File

@ -191,7 +191,7 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
#define S sym.get_addr(ctx)
#define A this->get_addend(rel)
#define P (output_section->shdr.sh_addr + offset + rel.r_offset)
#define G (sym.get_got_addr(ctx) - ctx.got->shdr.sh_addr)
#define G (sym.get_got_idx(ctx) * sizeof(Word<E>))
#define GOT ctx.got->shdr.sh_addr
switch (rel.r_type) {

View File

@ -130,7 +130,7 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
#define S sym.get_addr(ctx)
#define A this->get_addend(rel)
#define P (output_section->shdr.sh_addr + offset + rel.r_offset)
#define G (sym.get_got_addr(ctx) - ctx.got->shdr.sh_addr)
#define G (sym.get_got_idx(ctx) * sizeof(Word<E>))
#define GOT ctx.got->shdr.sh_addr
switch (rel.r_type) {
@ -214,32 +214,38 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
break;
}
case R_SPARC_GOTDATA_OP_HIX22:
if (sym.is_imported) {
*(ub32 *)loc |= bits((G >> 10) ^ (G >> 31), 21, 0);
} else {
// We always have to relax a GOT load to a load immediate if a
// symbol is local, because R_SPARC_GOTDATA_OP cannot represent
// an addend for a local symbol.
if (sym.is_imported) {
*(ub32 *)loc |= bits((G >> 10) ^ (G >> 31), 21, 0);
} else if (sym.is_absolute()) {
i64 val = S + A;
*(ub32 *)loc |= bits((val >> 10) ^ (val >> 31), 21, 0);
} else {
i64 val = S + A - GOT;
*(ub32 *)loc |= bits((val >> 10) ^ (val >> 31), 21, 0);
}
break;
case R_SPARC_GOTDATA_OP_LOX10:
case R_SPARC_GOTDATA_OP_LOX10: {
if (sym.is_imported) {
*(ub32 *)loc |= bits((G >> 10) ^ (G >> 31), 21, 0);
*(ub32 *)loc |= bits((G & 0x3ff) | ((G >> 31) & 0x1c00), 12, 0);
} else if (sym.is_absolute()) {
i64 val = S + A;
*(ub32 *)loc |= bits((val & 0x3ff) | ((val >> 31) & 0x1c00), 12, 0);
} else {
i64 val = S + A - GOT;
*(ub32 *)loc |= bits((val & 0x3ff) | ((val >> 31) & 0x1c00), 12, 0);
}
break;
}
case R_SPARC_GOTDATA_OP:
if (sym.is_imported)
break;
if (sym.is_remaining_undef_weak()) {
// ldx [ %g2 + %g1 ], %g1 → mov %g0, %g1
*(ub32 *)loc &= 0b00'11111'000000'00000'1'11111111'00000;
*(ub32 *)loc |= 0b10'00000'000010'00000'0'00000000'00000;
if (sym.is_absolute()) {
// ldx [ %g2 + %g1 ], %g1 → nop
*(ub32 *)loc = 0x0100'0000;
} else {
// ldx [ %g2 + %g1 ], %g1 → add %g2, %g1, %g1
*(ub32 *)loc &= 0b00'11111'000000'11111'1'11111111'11111;

View File

@ -1024,7 +1024,7 @@ void ObjectFile<E>::claim_unresolved_symbols(Context<E> &ctx) {
auto claim = [&] {
sym.file = this;
sym.set_input_section(nullptr);
sym.origin = 0;
sym.value = 0;
sym.sym_idx = i;
sym.is_weak = false;
@ -1438,7 +1438,7 @@ void SharedFile<E>::resolve_symbols(Context<E> &ctx) {
if (get_rank(this, esym, false) < get_rank(sym)) {
sym.file = this;
sym.set_input_section(nullptr);
sym.origin = 0;
sym.value = esym.st_value;
sym.sym_idx = i;
sym.ver_idx = versyms[i];

View File

@ -489,6 +489,7 @@ public:
u64 get_tlsld_addr(Context<E> &ctx) const;
i64 get_reldyn_size(Context<E> &ctx) const;
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
std::vector<Symbol<E> *> got_syms;
@ -1771,7 +1772,6 @@ public:
// If `file` is null, the symbol is equivalent to nonexistent.
InputFile<E> *file = nullptr;
private:
// A symbol usually belongs to an input section, but it can belong
// to a section fragment, an output section or nothing
// (i.e. absolute symbol). `origin` holds one of them. We use the
@ -1786,7 +1786,6 @@ private:
uintptr_t origin = 0;
public:
// `value` contains symbol value. If it's an absolute symbol, it is
// equivalent to its address. If it belongs to an input section or a
// section fragment, value is added to the base of the input section

View File

@ -1148,6 +1148,14 @@ std::vector<GotEntry<E>> GotSection<E>::get_entries(Context<E> &ctx) const {
return entries;
}
template <typename E>
void GotSection<E>::update_shdr(Context<E> &ctx) {
// We always create a .got so that _GLOBAL_OFFSET_TABLE_ refers
// a GOT section.
if (this->shdr.sh_size == 0)
this->shdr.sh_size = sizeof(Word<E>);
}
// Fill .got and .rel.dyn.
template <typename E>
void GotSection<E>::copy_buf(Context<E> &ctx) {

View File

@ -491,7 +491,7 @@ void add_synthetic_symbols(Context<E> &ctx) {
// Make the target absolute if necessary.
if (!target || target->is_absolute())
sym->set_input_section(nullptr);
sym->origin = 0;
}
}
@ -1688,9 +1688,8 @@ void fix_synthetic_symbols(Context<E> &ctx) {
Symbol<E> *sym = ctx.arg.defsyms[i].first;
std::variant<Symbol<E> *, u64> val = ctx.arg.defsyms[i].second;
sym->set_input_section(nullptr);
if (u64 *addr = std::get_if<u64>(&val)) {
sym->origin = 0;
sym->value = *addr;
continue;
}
@ -1701,11 +1700,9 @@ void fix_synthetic_symbols(Context<E> &ctx) {
continue;
}
sym->value = sym2->get_addr(ctx);
sym->value = sym2->value;
sym->origin = sym2->origin;
sym->visibility = sym2->visibility.load();
if (InputSection<E> *isec = sym2->get_input_section())
sym->set_output_section(isec->output_section);
}
}

View File

@ -299,7 +299,7 @@ void ROutputEhdr<E>::write_to(Context<E> &ctx) {
ElfEhdr<E> &hdr = *(ElfEhdr<E> *)(ctx.buf + this->out_shdr.sh_offset);
memcpy(&hdr.e_ident, "\177ELF", 4);
hdr.e_ident[EI_CLASS] = E::is_64 ? ELFCLASS64 : ELFCLASS32;
hdr.e_ident[EI_DATA] = ELFDATA2LSB;
hdr.e_ident[EI_DATA] = E::is_le ? ELFDATA2LSB : ELFDATA2MSB;
hdr.e_ident[EI_VERSION] = EV_CURRENT;
hdr.e_type = ET_REL;
hdr.e_machine = E::e_machine;
@ -398,7 +398,7 @@ void RObjectFile<E>::remove_comdats(Context<E> &ctx,
continue;
// If it is a duplicate, remove it and its members.
for (i64 j : this->template get_data<u32>(ctx, shdr).subspan(1))
for (i64 j : this->template get_data<U32<E>>(ctx, shdr).subspan(1))
sections[j] = nullptr;
sections[i] = nullptr;
}

View File

@ -21,6 +21,5 @@ EOF
readelf -W --sections $t/exe > $t/log
! grep -Fq ' .dynsym ' $t/log || false
! grep -Fq ' .dynstr ' $t/log || false
! grep -Fq ' .got ' $t/log || false
echo OK