1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-20 09:27:45 +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 S sym.get_addr(ctx)
#define A this->get_addend(rel) #define A this->get_addend(rel)
#define P (output_section->shdr.sh_addr + offset + rel.r_offset) #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 #define GOT ctx.got->shdr.sh_addr
switch (rel.r_type) { 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 S sym.get_addr(ctx)
#define A this->get_addend(rel) #define A this->get_addend(rel)
#define P (output_section->shdr.sh_addr + offset + rel.r_offset) #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 #define GOT ctx.got->shdr.sh_addr
switch (rel.r_type) { switch (rel.r_type) {
@ -214,32 +214,38 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
break; break;
} }
case R_SPARC_GOTDATA_OP_HIX22: case R_SPARC_GOTDATA_OP_HIX22:
// 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) { if (sym.is_imported) {
*(ub32 *)loc |= bits((G >> 10) ^ (G >> 31), 21, 0); *(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 { } 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.
i64 val = S + A - GOT; i64 val = S + A - GOT;
*(ub32 *)loc |= bits((val >> 10) ^ (val >> 31), 21, 0); *(ub32 *)loc |= bits((val >> 10) ^ (val >> 31), 21, 0);
} }
break; break;
case R_SPARC_GOTDATA_OP_LOX10: case R_SPARC_GOTDATA_OP_LOX10: {
if (sym.is_imported) { 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 { } else {
i64 val = S + A - GOT; i64 val = S + A - GOT;
*(ub32 *)loc |= bits((val & 0x3ff) | ((val >> 31) & 0x1c00), 12, 0); *(ub32 *)loc |= bits((val & 0x3ff) | ((val >> 31) & 0x1c00), 12, 0);
} }
break; break;
}
case R_SPARC_GOTDATA_OP: case R_SPARC_GOTDATA_OP:
if (sym.is_imported) if (sym.is_imported)
break; break;
if (sym.is_remaining_undef_weak()) { if (sym.is_absolute()) {
// ldx [ %g2 + %g1 ], %g1 → mov %g0, %g1 // ldx [ %g2 + %g1 ], %g1 → nop
*(ub32 *)loc &= 0b00'11111'000000'00000'1'11111111'00000; *(ub32 *)loc = 0x0100'0000;
*(ub32 *)loc |= 0b10'00000'000010'00000'0'00000000'00000;
} else { } else {
// ldx [ %g2 + %g1 ], %g1 → add %g2, %g1, %g1 // ldx [ %g2 + %g1 ], %g1 → add %g2, %g1, %g1
*(ub32 *)loc &= 0b00'11111'000000'11111'1'11111111'11111; *(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 = [&] { auto claim = [&] {
sym.file = this; sym.file = this;
sym.set_input_section(nullptr); sym.origin = 0;
sym.value = 0; sym.value = 0;
sym.sym_idx = i; sym.sym_idx = i;
sym.is_weak = false; 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)) { if (get_rank(this, esym, false) < get_rank(sym)) {
sym.file = this; sym.file = this;
sym.set_input_section(nullptr); sym.origin = 0;
sym.value = esym.st_value; sym.value = esym.st_value;
sym.sym_idx = i; sym.sym_idx = i;
sym.ver_idx = versyms[i]; sym.ver_idx = versyms[i];

View File

@ -489,6 +489,7 @@ public:
u64 get_tlsld_addr(Context<E> &ctx) const; u64 get_tlsld_addr(Context<E> &ctx) const;
i64 get_reldyn_size(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; void copy_buf(Context<E> &ctx) override;
std::vector<Symbol<E> *> got_syms; std::vector<Symbol<E> *> got_syms;
@ -1771,7 +1772,6 @@ public:
// If `file` is null, the symbol is equivalent to nonexistent. // If `file` is null, the symbol is equivalent to nonexistent.
InputFile<E> *file = nullptr; InputFile<E> *file = nullptr;
private:
// A symbol usually belongs to an input section, but it can belong // A symbol usually belongs to an input section, but it can belong
// to a section fragment, an output section or nothing // to a section fragment, an output section or nothing
// (i.e. absolute symbol). `origin` holds one of them. We use the // (i.e. absolute symbol). `origin` holds one of them. We use the
@ -1786,7 +1786,6 @@ private:
uintptr_t origin = 0; uintptr_t origin = 0;
public:
// `value` contains symbol value. If it's an absolute symbol, it is // `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 // 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 // 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; 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. // Fill .got and .rel.dyn.
template <typename E> template <typename E>
void GotSection<E>::copy_buf(Context<E> &ctx) { 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. // Make the target absolute if necessary.
if (!target || target->is_absolute()) 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; Symbol<E> *sym = ctx.arg.defsyms[i].first;
std::variant<Symbol<E> *, u64> val = ctx.arg.defsyms[i].second; std::variant<Symbol<E> *, u64> val = ctx.arg.defsyms[i].second;
sym->set_input_section(nullptr);
if (u64 *addr = std::get_if<u64>(&val)) { if (u64 *addr = std::get_if<u64>(&val)) {
sym->origin = 0;
sym->value = *addr; sym->value = *addr;
continue; continue;
} }
@ -1701,11 +1700,9 @@ void fix_synthetic_symbols(Context<E> &ctx) {
continue; continue;
} }
sym->value = sym2->get_addr(ctx); sym->value = sym2->value;
sym->origin = sym2->origin;
sym->visibility = sym2->visibility.load(); 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); ElfEhdr<E> &hdr = *(ElfEhdr<E> *)(ctx.buf + this->out_shdr.sh_offset);
memcpy(&hdr.e_ident, "\177ELF", 4); memcpy(&hdr.e_ident, "\177ELF", 4);
hdr.e_ident[EI_CLASS] = E::is_64 ? ELFCLASS64 : ELFCLASS32; 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_ident[EI_VERSION] = EV_CURRENT;
hdr.e_type = ET_REL; hdr.e_type = ET_REL;
hdr.e_machine = E::e_machine; hdr.e_machine = E::e_machine;
@ -398,7 +398,7 @@ void RObjectFile<E>::remove_comdats(Context<E> &ctx,
continue; continue;
// If it is a duplicate, remove it and its members. // 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[j] = nullptr;
sections[i] = nullptr; sections[i] = nullptr;
} }

View File

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