Skip to content

Commit

Permalink
[ELF] Fix "recompile with -fPIC" error
Browse files Browse the repository at this point in the history
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 #116
  • Loading branch information
rui314 committed Sep 27, 2021
1 parent dc672ad commit d7412d6
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 8 deletions.
2 changes: 1 addition & 1 deletion elf/arch-aarch64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion elf/arch-i386.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion elf/arch-x86-64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
5 changes: 4 additions & 1 deletion elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,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 false),
// 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);
Expand Down
6 changes: 4 additions & 2 deletions test/func-addr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d7412d6

Please sign in to comment.