[PATCH] D33680: [ELF] - Resolve references properly when using .symver directive

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 29 11:46:52 PDT 2017


LGTM

George Rimar via Phabricator <reviews at reviews.llvm.org> writes:

> grimar updated this revision to Diff 104622.
> grimar added a comment.
>
> - Addressed review comments.
>
>
> https://reviews.llvm.org/D33680
>
> Files:
>   ELF/SymbolTable.cpp
>   test/ELF/version-script-symver.s
>
>
> Index: test/ELF/version-script-symver.s
> ===================================================================
> --- test/ELF/version-script-symver.s
> +++ test/ELF/version-script-symver.s
> @@ -0,0 +1,11 @@
> +# REQUIRES: x86
> +
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
> +# RUN: echo "VERSION { global: *; };" > %t.map
> +# RUN: ld.lld %t.o --version-script %t.map -o %t
> +
> +.global _start
> +.global bar
> +.symver _start, bar@@VERSION
> +_start:
> +  jmp bar
> Index: ELF/SymbolTable.cpp
> ===================================================================
> --- ELF/SymbolTable.cpp
> +++ ELF/SymbolTable.cpp
> @@ -712,15 +712,31 @@
>        B->symbol()->VersionId = VersionId;
>  }
>  
> +static bool isDefaultVersion(SymbolBody *B) {
> +  return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos;
> +}
> +
>  // This function processes version scripts by updating VersionId
>  // member of symbols.
>  template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
>    // Symbol themselves might know their versions because symbols
>    // can contain versions in the form of <name>@<version>.
> -  // Let them parse their names.
> -  if (!Config->VersionDefinitions.empty())
> -    for (Symbol *Sym : SymVector)
> -      Sym->body()->parseSymbolVersion();
> +  // Let them parse and update their names to exclude version suffix.
> +  for (Symbol *Sym : SymVector) {
> +    SymbolBody *Body = Sym->body();
> +    bool IsDefault = isDefaultVersion(Body);
> +    Body->parseSymbolVersion();
> +
> +    if (!IsDefault)
> +      continue;
> +
> +    // <name>@@<version> means the symbol is the default version. If that's the
> +    // case, the symbol is not used only to resolve <name> of version <version>
> +    // but also undefined unversioned symbols with name <name>.
> +    SymbolBody *S = find(Body->getName());
> +    if (S && S->isUndefined())
> +      S->copy(Body);
> +  }
>  
>    // Handle edge cases first.
>    handleAnonymousVersion();
>
>
> Index: test/ELF/version-script-symver.s
> ===================================================================
> --- test/ELF/version-script-symver.s
> +++ test/ELF/version-script-symver.s
> @@ -0,0 +1,11 @@
> +# REQUIRES: x86
> +
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
> +# RUN: echo "VERSION { global: *; };" > %t.map
> +# RUN: ld.lld %t.o --version-script %t.map -o %t
> +
> +.global _start
> +.global bar
> +.symver _start, bar@@VERSION
> +_start:
> +  jmp bar
> Index: ELF/SymbolTable.cpp
> ===================================================================
> --- ELF/SymbolTable.cpp
> +++ ELF/SymbolTable.cpp
> @@ -712,15 +712,31 @@
>        B->symbol()->VersionId = VersionId;
>  }
>  
> +static bool isDefaultVersion(SymbolBody *B) {
> +  return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos;
> +}
> +
>  // This function processes version scripts by updating VersionId
>  // member of symbols.
>  template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
>    // Symbol themselves might know their versions because symbols
>    // can contain versions in the form of <name>@<version>.
> -  // Let them parse their names.
> -  if (!Config->VersionDefinitions.empty())
> -    for (Symbol *Sym : SymVector)
> -      Sym->body()->parseSymbolVersion();
> +  // Let them parse and update their names to exclude version suffix.
> +  for (Symbol *Sym : SymVector) {
> +    SymbolBody *Body = Sym->body();
> +    bool IsDefault = isDefaultVersion(Body);
> +    Body->parseSymbolVersion();
> +
> +    if (!IsDefault)
> +      continue;
> +
> +    // <name>@@<version> means the symbol is the default version. If that's the
> +    // case, the symbol is not used only to resolve <name> of version <version>
> +    // but also undefined unversioned symbols with name <name>.
> +    SymbolBody *S = find(Body->getName());
> +    if (S && S->isUndefined())
> +      S->copy(Body);
> +  }
>  
>    // Handle edge cases first.
>    handleAnonymousVersion();


More information about the llvm-commits mailing list