From bd7735f79765e826c23d48d23c0ad327c9393f90 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Thu, 31 Jan 2019 16:45:16 +0000 Subject: [PATCH] [llvm-objcopy] Skip --localize-symbol for undefined symbols Summary: Include the symbol being defined in the list of requirements for using --localize-symbol. This is used, for example, when someone is depending on two different projects that have the same (or close enough) method defined in each library, and using "-L sym" for a conflicting symbol in one of the libraries so that the definition from the other one is used. However, the library may have internal references to the symbol, which cause program crashes when those are used, i.e.: ``` $ cat foo.c int foo() { return 5; } $ cat bar.c int foo(); int bar() { return 2 * foo(); } $ cat foo2.c int foo() { /* Safer implementation */ return 42; } $ cat main.c int bar(); int main() { __builtin_printf("bar = %d\n", bar()); return 0; } $ ar rcs libfoo.a foo.o bar.o $ ar rcs libfoo2.a foo2.o # Picks the wrong foo() impl $ clang main.o -lfoo -lfoo2 -L. -o main # Picks the right foo() impl $ objcopy -L foo libfoo.a && clang main.o -lfoo -lfoo2 -L. -o main # Links somehow, but crashes at runtime $ llvm-objcopy -L foo libfoo.a && clang main.o -lfoo -lfoo2 -L. -o main ``` Reviewers: jhenderson, alexshap, jakehehrlich, espindola Subscribers: emaste, arichardson Differential Revision: https://reviews.llvm.org/D57417 llvm-svn: 352767 --- llvm/test/tools/llvm-objcopy/ELF/localize.test | 12 ++++++++++++ llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/llvm/test/tools/llvm-objcopy/ELF/localize.test b/llvm/test/tools/llvm-objcopy/ELF/localize.test index a04c51d8fc105..50cdce78da163 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/localize.test +++ b/llvm/test/tools/llvm-objcopy/ELF/localize.test @@ -1,6 +1,7 @@ # RUN: yaml2obj %s > %t # RUN: llvm-objcopy \ # RUN: --localize-symbol Global \ +# RUN: -L GlobalUndef \ # RUN: -L Local \ # RUN: -L Weak \ # RUN: -L GlobalCommon \ @@ -45,6 +46,8 @@ Symbols: Size: 8 Section: .text Value: 0x1010 + - Name: GlobalUndef + Type: STT_FUNC - Name: GlobalCommon Type: STT_OBJECT Index: SHN_COMMON @@ -89,6 +92,15 @@ Symbols: #CHECK-NEXT: Section: .text #CHECK-NEXT: } #CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: GlobalUndef +#CHECK-NEXT: Value: +#CHECK-NEXT: Size: +#CHECK-NEXT: Binding: Global +#CHECK-NEXT: Type: Function +#CHECK-NEXT: Other: +#CHECK-NEXT: Section: Undefined +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { #CHECK-NEXT: Name: GlobalCommon #CHECK-NEXT: Value: 0x2006 #CHECK-NEXT: Size: 2 diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp index e77361e285a0e..2dd2fe9c9a9b0 100644 --- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -287,7 +287,9 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj, // them. if (Obj.SymbolTable) { Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { - if (!Sym.isCommon() && + // Common and undefined symbols don't make sense as local symbols, and can + // even cause crashes if we localize those, so skip them. + if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF && ((Config.LocalizeHidden && (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || is_contained(Config.SymbolsToLocalize, Sym.Name)))