Skip to content

Commit

Permalink
[ELF] - Fix missing relocation when linking executable with --unresol…
Browse files Browse the repository at this point in the history
…ved-symbols=ignore-all

This is PR32112. Previously when we linked executable with 
--unresolved-symbols=ignore-all and undefined symbols, like:

_start:
callq und@PLT

we did not create relocations, though it looks in that case
we should delegate handling of such symbols to runtime linker,
hence should emit them. Patch fixes that.

Differential revision: https://reviews.llvm.org/D35724

llvm-svn: 309252
  • Loading branch information
George Rimar committed Jul 27, 2017
1 parent 88ac9a8 commit 678188d
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
20 changes: 14 additions & 6 deletions lld/ELF/Symbols.cpp
Expand Up @@ -141,10 +141,6 @@ bool SymbolBody::isPreemptible() const {
if (isShared())
return !NeedsCopy && !NeedsPltAddr;

// That's all that can be preempted in a non-DSO.
if (!Config->Shared)
return false;

// Only symbols that appear in dynsym can be preempted.
if (!symbol()->includeInDynsym())
return false;
Expand All @@ -153,6 +149,15 @@ bool SymbolBody::isPreemptible() const {
if (symbol()->Visibility != STV_DEFAULT)
return false;

// Undefined symbols in non-DSOs are usually just an error, so it
// doesn't matter whether we return true or false here. However, if
// -unresolved-symbols=ignore-all is specified, undefined symbols in
// executables are automatically exported so that the runtime linker
// can try to resolve them. In that case, they is preemptible. So, we
// return true for an undefined symbol in case the option is specified.
if (!Config->Shared)
return isUndefined();

// -Bsymbolic means that definitions are not preempted.
if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc()))
return !isDefined();
Expand Down Expand Up @@ -357,8 +362,11 @@ uint8_t Symbol::computeBinding() const {
bool Symbol::includeInDynsym() const {
if (computeBinding() == STB_LOCAL)
return false;
return ExportDynamic || body()->isShared() ||
(body()->isUndefined() && Config->Shared);
if (ExportDynamic || body()->isShared())
return true;
if (!body()->isUndefined())
return false;
return Config->Shared || !body()->symbol()->isWeak();
}

// Print out a log message for --trace-symbol.
Expand Down
13 changes: 13 additions & 0 deletions lld/test/ELF/executable-undefined-ignoreall.s
@@ -0,0 +1,13 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
# RUN: ld.lld %t -o %tout --unresolved-symbols=ignore-all -pie
# RUN: llvm-readobj -r %tout | FileCheck %s

# CHECK: Relocations [
# CHECK-NEXT: Section ({{.*}}) .rela.plt {
# CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT foo 0x0
# CHECK-NEXT: }
# CHECK-NEXT: ]

_start:
callq foo@PLT
8 changes: 8 additions & 0 deletions lld/test/ELF/executable-undefined-protected-ignoreall.s
@@ -0,0 +1,8 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
# RUN: not ld.lld %t -o %tout --unresolved-symbols=ignore-all -pie 2>&1 | FileCheck %s
# CHECK: error: undefined symbol: foo

.protected foo
_start:
callq foo@PLT
6 changes: 5 additions & 1 deletion lld/test/ELF/no-inhibit-exec.s
Expand Up @@ -2,11 +2,15 @@
# RUN: not ld.lld %t -o %t2
# RUN: ld.lld %t --noinhibit-exec -o %t2
# RUN: llvm-objdump -d %t2 | FileCheck %s
# RUN: llvm-readobj -r %t2 | FileCheck %s --check-prefix=RELOC
# REQUIRES: x86

# CHECK: Disassembly of section .text:
# CHECK-NEXT: _start
# CHECK-NEXT: 201000: {{.*}} callq -2101253
# CHECK-NEXT: 201000: {{.*}} callq 0

# RELOC: Relocations [
# RELOC: ]

# next code will not link without noinhibit-exec flag
# because of undefined symbol _bar
Expand Down

0 comments on commit 678188d

Please sign in to comment.