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:
parent
139aae9444
commit
9dcc70f6ee
@ -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) {
|
||||
|
@ -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:
|
||||
// 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 {
|
||||
// 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;
|
||||
*(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;
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user