From b0d9fbeeebcc493212946770d1acb584e30d15e5 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Wed, 2 Aug 2017 07:51:08 +0000 Subject: [PATCH] [ELF] - Recommit r309252 "[ELF] - Fix missing relocation when linking executable with --unresolved-symbols=ignore-all" With fix for undefined weak symbols in executable. Original commit message: 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: 309796 --- lld/ELF/Symbols.cpp | 15 ++++++++++----- lld/test/ELF/executable-undefined-ignoreall.s | 13 +++++++++++++ .../executable-undefined-protected-ignoreall.s | 8 ++++++++ lld/test/ELF/no-inhibit-exec.s | 6 +++++- 4 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 lld/test/ELF/executable-undefined-ignoreall.s create mode 100644 lld/test/ELF/executable-undefined-protected-ignoreall.s diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index d3f6cc619ce1..61032a6368dd 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -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; @@ -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(); @@ -358,7 +363,7 @@ bool Symbol::includeInDynsym() const { if (computeBinding() == STB_LOCAL) return false; if (body()->isUndefined()) - return Config->Shared; + return Config->Shared || !body()->symbol()->isWeak(); return ExportDynamic || body()->isShared(); } diff --git a/lld/test/ELF/executable-undefined-ignoreall.s b/lld/test/ELF/executable-undefined-ignoreall.s new file mode 100644 index 000000000000..44f83a687ee2 --- /dev/null +++ b/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 diff --git a/lld/test/ELF/executable-undefined-protected-ignoreall.s b/lld/test/ELF/executable-undefined-protected-ignoreall.s new file mode 100644 index 000000000000..37911791e124 --- /dev/null +++ b/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 diff --git a/lld/test/ELF/no-inhibit-exec.s b/lld/test/ELF/no-inhibit-exec.s index d0970d93f21e..ad60f1c652f6 100644 --- a/lld/test/ELF/no-inhibit-exec.s +++ b/lld/test/ELF/no-inhibit-exec.s @@ -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: ] # next code will not link without noinhibit-exec flag # because of undefined symbol _bar