1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-21 18:08:01 +03:00

[ELF] Fix "recompile with -fPIC" error

mold used to emit a spurious "recompile with -fPIC" error when creating
a position-dependent executable. This is because we alwyas create
dynamic relocations for importe symbols. If the relocated place is
read-only, we can't apply a dynamic relocation, and we printed out the
error message.

This patch fixes the issue by creating copy relocations and PLTs for
such symbols.

Fixes https://github.com/rui314/mold/issues/116
This commit is contained in:
Rui Ueyama 2021-09-25 18:10:26 +09:00
parent d11ecda08c
commit e4861bb3e1
6 changed files with 12 additions and 8 deletions

View File

@ -398,7 +398,7 @@ void InputSection<AARCH64>::scan_relocations(Context<AARCH64> &ctx) {
// Absolute Local Imported data Imported code
{ NONE, BASEREL, DYNREL, DYNREL }, // DSO
{ NONE, BASEREL, DYNREL, DYNREL }, // PIE
{ NONE, NONE, DYNREL, DYNREL }, // PDE
{ NONE, NONE, COPYREL, PLT }, // PDE
};
dispatch(ctx, table, i);
break;

View File

@ -404,7 +404,7 @@ void InputSection<I386>::scan_relocations(Context<I386> &ctx) {
// Absolute Local Imported data Imported code
{ NONE, BASEREL, DYNREL, DYNREL }, // DSO
{ NONE, BASEREL, DYNREL, DYNREL }, // PIE
{ NONE, NONE, DYNREL, DYNREL }, // PDE
{ NONE, NONE, COPYREL, PLT }, // PDE
};
dispatch(ctx, table, i);
break;

View File

@ -556,7 +556,7 @@ void InputSection<X86_64>::scan_relocations(Context<X86_64> &ctx) {
// Absolute Local Imported data Imported code
{ NONE, BASEREL, DYNREL, DYNREL }, // DSO
{ NONE, BASEREL, DYNREL, DYNREL }, // PIE
{ NONE, NONE, DYNREL, DYNREL }, // PDE
{ NONE, NONE, COPYREL, PLT }, // PDE
};
dispatch(ctx, table, i);
break;

View File

@ -861,7 +861,6 @@ void GotSection<E>::copy_buf(Context<E> &ctx) {
template <typename E>
void PltSection<E>::add_symbol(Context<E> &ctx, Symbol<E> *sym) {
assert(!sym->has_plt(ctx));
assert(!sym->has_got(ctx));
if (this->shdr.sh_size == 0) {
this->shdr.sh_size = E::plt_hdr_size;
@ -1005,7 +1004,7 @@ void DynsymSection<E>::copy_buf(Context<E> &ctx) {
} else if (sym.file->is_dso || sym.esym().is_undef()) {
esym.st_shndx = SHN_UNDEF;
esym.st_size = 0;
if (!ctx.arg.pic && sym.has_plt(ctx) && !sym.has_got(ctx)) {
if (sym.has_plt(ctx) && !ctx.arg.pic) {
// Emit an address for a canonical PLT
esym.st_value = sym.get_plt_addr(ctx);
}

View File

@ -537,7 +537,10 @@ void scan_rels(Context<E> &ctx) {
ctx.got->add_got_symbol(ctx, sym);
if (sym->flags & NEEDS_PLT) {
if (sym->flags & NEEDS_GOT)
// If we need to create a canonical PLT (i.e. ctx.arg.pic is true),
// we can't use .plt.got because otherwise .plt.got and .plt would
// refer each other, resulting in an infinite loop at runtime.
if ((sym->flags & NEEDS_GOT) && !ctx.arg.pic)
ctx.pltgot->add_symbol(ctx, sym);
else
ctx.plt->add_symbol(ctx, sym);

View File

@ -10,11 +10,13 @@ cat <<EOF | cc -shared -o $t/a.so -xc -
void fn() {}
EOF
cat <<EOF | cc -o $t/b.o -c -xc -
cat <<EOF | cc -o $t/b.o -c -xc -fno-PIC -
#include <stdio.h>
typedef void Func();
void fn();
void (*ptr)() = fn;
Func *const ptr = fn;
int main() {
printf("%d\n", fn == ptr);