[lld] r249998 - ELF2: Implement --as-needed.

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 11 18:48:13 PDT 2015


There is something missing on the test. Everything still passes if I convert

if (Body && Body->isUndefined() && !Body->isWeak())

to just

if (Body)

Cheers,
Rafael



On 11 October 2015 at 16:59, Rui Ueyama via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: ruiu
> Date: Sun Oct 11 15:59:12 2015
> New Revision: 249998
>
> URL: http://llvm.org/viewvc/llvm-project?rev=249998&view=rev
> Log:
> ELF2: Implement --as-needed.
>
> This patch adds AsNeeded and IsUsed bool fields to SharedFile. AsNeeded bit
> is set if the DSO is enclosed with --as-needed and --no-as-needed. IsUsed
> bit is off by default. When we adds a symbol to the symbol table for dynamic
> linking, we set its SharedFile's IsUsed bit.
>
> If AsNeeded is set but IsUsed is not set, we don't want to write that
> file's SO name to DT_NEEDED field.
>
> http://reviews.llvm.org/D13579
>
> Added:
>     lld/trunk/test/elf2/Inputs/shared2.s
>     lld/trunk/test/elf2/Inputs/shared3.s
>     lld/trunk/test/elf2/as-needed.s
> Modified:
>     lld/trunk/ELF/Config.h
>     lld/trunk/ELF/Driver.cpp
>     lld/trunk/ELF/InputFiles.cpp
>     lld/trunk/ELF/InputFiles.h
>     lld/trunk/ELF/InputSection.cpp
>     lld/trunk/ELF/LinkerScript.cpp
>     lld/trunk/ELF/Options.td
>     lld/trunk/ELF/OutputSections.cpp
>     lld/trunk/ELF/Symbols.h
>     lld/trunk/ELF/Writer.cpp
>
> Modified: lld/trunk/ELF/Config.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Config.h (original)
> +++ lld/trunk/ELF/Config.h Sun Oct 11 15:59:12 2015
> @@ -43,6 +43,7 @@ struct Configuration {
>    std::string RPath;
>    std::vector<llvm::StringRef> SearchPaths;
>    bool AllowMultipleDefinition;
> +  bool AsNeeded = false;
>    bool DiscardAll;
>    bool DiscardLocals;
>    bool DiscardNone;
>
> Modified: lld/trunk/ELF/Driver.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Driver.cpp (original)
> +++ lld/trunk/ELF/Driver.cpp Sun Oct 11 15:59:12 2015
> @@ -100,9 +100,12 @@ void LinkerDriver::addFile(StringRef Pat
>      }
>      Files.push_back(make_unique<ArchiveFile>(MBRef));
>      return;
> -  case file_magic::elf_shared_object:
> -    Files.push_back(createELFFile<SharedFile>(MBRef));
> +  case file_magic::elf_shared_object: {
> +    std::unique_ptr<ELFFileBase> File = createELFFile<SharedFile>(MBRef);
> +    cast<SharedFileBase>(File.get())->AsNeeded = Config->AsNeeded;
> +    Files.push_back(std::move(File));
>      return;
> +  }
>    default:
>      Files.push_back(createELFFile<ObjectFile>(MBRef));
>    }
> @@ -187,6 +190,12 @@ void LinkerDriver::createFiles(opt::Inpu
>      case OPT_script:
>        addFile(Arg->getValue());
>        break;
> +    case OPT_as_needed:
> +      Config->AsNeeded = true;
> +      break;
> +    case OPT_no_as_needed:
> +      Config->AsNeeded = false;
> +      break;
>      case OPT_Bstatic:
>        Config->Static = true;
>        break;
>
> Modified: lld/trunk/ELF/InputFiles.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputFiles.cpp (original)
> +++ lld/trunk/ELF/InputFiles.cpp Sun Oct 11 15:59:12 2015
> @@ -329,7 +329,7 @@ template <class ELFT> void SharedFile<EL
>      error(NameOrErr.getError());
>      StringRef Name = *NameOrErr;
>
> -    SymbolBodies.emplace_back(Name, Sym);
> +    SymbolBodies.emplace_back(this, Name, Sym);
>    }
>  }
>
>
> Modified: lld/trunk/ELF/InputFiles.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputFiles.h (original)
> +++ lld/trunk/ELF/InputFiles.h Sun Oct 11 15:59:12 2015
> @@ -146,7 +146,7 @@ public:
>      uint32_t FirstNonLocal = this->Symtab->sh_info;
>      if (SymbolIndex < FirstNonLocal)
>        return nullptr;
> -    return SymbolBodies[SymbolIndex - FirstNonLocal]->repl();
> +    return SymbolBodies[SymbolIndex - FirstNonLocal];
>    }
>
>    Elf_Sym_Range getLocalSymbols();
> @@ -198,6 +198,11 @@ public:
>    StringRef getSoName() const { return SoName; }
>    virtual void parseSoName() = 0;
>    virtual void parse() = 0;
> +
> +  // Used for --as-needed
> +  bool AsNeeded = false;
> +  bool IsUsed = false;
> +  bool isNeeded() const { return !AsNeeded || IsUsed; }
>  };
>
>  template <class ELFT>
>
> Modified: lld/trunk/ELF/InputSection.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputSection.cpp (original)
> +++ lld/trunk/ELF/InputSection.cpp Sun Oct 11 15:59:12 2015
> @@ -46,7 +46,7 @@ void InputSection<ELFT>::relocate(
>          continue;
>        SymVA = getLocalSymVA(Sym, File);
>      } else {
> -      SymbolBody &Body = *File.getSymbolBody(SymIndex);
> +      SymbolBody &Body = *File.getSymbolBody(SymIndex)->repl();
>        SymVA = getSymVA<ELFT>(Body);
>        if (Target->relocNeedsPlt(Type, Body)) {
>          SymVA = Out<ELFT>::Plt->getEntryAddr(Body);
>
> Modified: lld/trunk/ELF/LinkerScript.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/LinkerScript.cpp (original)
> +++ lld/trunk/ELF/LinkerScript.cpp Sun Oct 11 15:59:12 2015
> @@ -155,12 +155,15 @@ void LinkerScript::addFile(StringRef S)
>
>  void LinkerScript::readAsNeeded() {
>    expect("(");
> +  bool Orig = Config->AsNeeded;
> +  Config->AsNeeded = true;
>    for (;;) {
>      StringRef Tok = next();
>      if (Tok == ")")
> -      return;
> +      break;
>      addFile(Tok);
>    }
> +  Config->AsNeeded = Orig;
>  }
>
>  void LinkerScript::readEntry() {
>
> Modified: lld/trunk/ELF/Options.td
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Options.td (original)
> +++ lld/trunk/ELF/Options.td Sun Oct 11 15:59:12 2015
> @@ -14,6 +14,8 @@ def allow_multiple_definition: Flag<["--
>
>  def allow_shlib_undefined : Flag<["--", "-"], "allow-shlib-undefined">;
>
> +def as_needed : Flag<["--"], "as-needed">;
> +
>  def disable_new_dtags : Flag<["--"], "disable-new-dtags">,
>    HelpText<"Disable new dynamic tags">;
>
> @@ -52,6 +54,8 @@ def m : Separate<["-"], "m">,
>
>  def no_allow_shlib_undefined : Flag<["--"], "no-allow-shlib-undefined">;
>
> +def no_as_needed : Flag<["--"], "no-as-needed">;
> +
>  def no_whole_archive : Flag<["--"], "no-whole-archive">,
>    HelpText<"Restores the default behavior of loading archive members">;
>
> @@ -111,14 +115,12 @@ def alias_undefined_u : Separate<["-"],
>
>  // Options listed below are silently ignored now.
>  def O3 : Flag<["-"], "O3">;
> -def as_needed : Flag<["--"], "as-needed">;
>  def build_id : Flag<["--"], "build-id">;
>  def eh_frame_hdr : Flag<["--"], "eh-frame-hdr">;
>  def end_group : Flag<["--"], "end-group">;
>  def gc_sections : Flag<["--"], "gc-sections">;
>  def hash_style : Joined<["--"], "hash-style=">;
>  def no_add_needed : Flag<["--"], "no-add-needed">;
> -def no_as_needed : Flag<["--"], "no-as-needed">;
>  def no_fatal_warnings : Flag<["--"], "no-fatal-warnings">;
>  def start_group : Flag<["--"], "start-group">;
>  def strip_all : Flag<["--"], "strip-all">;
>
> Modified: lld/trunk/ELF/OutputSections.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/OutputSections.cpp (original)
> +++ lld/trunk/ELF/OutputSections.cpp Sun Oct 11 15:59:12 2015
> @@ -116,8 +116,10 @@ template <class ELFT> void RelocationSec
>      OutputSection<ELFT> *OutSec = C.getOutputSection();
>      uint32_t SymIndex = RI.getSymbol(IsMips64EL);
>      const ObjectFile<ELFT> &File = *C.getFile();
> -    const SymbolBody *Body = File.getSymbolBody(SymIndex);
> +    SymbolBody *Body = File.getSymbolBody(SymIndex);
>      const ELFFile<ELFT> &Obj = File.getObj();
> +    if (Body)
> +      Body = Body->repl();
>
>      uint32_t Type = RI.getType(IsMips64EL);
>
> @@ -279,6 +281,8 @@ template <class ELFT> void DynamicSectio
>      NumEntries += 2;
>
>    for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) {
> +    if (!F->isNeeded())
> +      continue;
>      Out<ELFT>::DynStrTab->add(F->getSoName());
>      ++NumEntries;
>    }
> @@ -356,7 +360,8 @@ template <class ELFT> void DynamicSectio
>    WriteArray(DT_FINI_ARRAY, DT_FINI_ARRAYSZ, FiniArraySec);
>
>    for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
> -    WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->getFileOff(F->getSoName()));
> +    if (F->isNeeded())
> +      WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->getFileOff(F->getSoName()));
>
>    if (InitSym)
>      WritePtr(DT_INIT, getSymVA<ELFT>(*InitSym));
>
> Modified: lld/trunk/ELF/Symbols.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Symbols.h (original)
> +++ lld/trunk/ELF/Symbols.h Sun Oct 11 15:59:12 2015
> @@ -24,6 +24,7 @@ class InputFile;
>  class SymbolBody;
>  template <class ELFT> class ObjectFile;
>  template <class ELFT> class OutputSection;
> +template <class ELFT> class SharedFile;
>
>  // Initializes global objects defined in this file.
>  // Called at the beginning of main().
> @@ -263,8 +264,10 @@ public:
>      return S->kind() == Base::SharedKind;
>    }
>
> -  SharedSymbol(StringRef Name, const Elf_Sym &Sym)
> -      : Defined<ELFT>(Base::SharedKind, Name, Sym) {}
> +  SharedSymbol(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym)
> +      : Defined<ELFT>(Base::SharedKind, Name, Sym), File(F) {}
> +
> +  SharedFile<ELFT> *File;
>  };
>
>  // This class represents a symbol defined in an archive file. It is
>
> Modified: lld/trunk/ELF/Writer.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=249998&r1=249997&r2=249998&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Sun Oct 11 15:59:12 2015
> @@ -174,6 +174,14 @@ void Writer<ELFT>::scanRelocs(
>      uint32_t SymIndex = RI.getSymbol(IsMips64EL);
>      SymbolBody *Body = File.getSymbolBody(SymIndex);
>      uint32_t Type = RI.getType(IsMips64EL);
> +
> +    // Set "used" bit for --as-needed.
> +    if (Body && Body->isUndefined() && !Body->isWeak())
> +      if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl()))
> +        S->File->IsUsed = true;
> +
> +    if (Body)
> +      Body = Body->repl();
>      if (Body) {
>        if (Target->relocNeedsPlt(Type, *Body)) {
>          if (Body->isInPlt())
> @@ -186,12 +194,13 @@ void Writer<ELFT>::scanRelocs(
>          Out<ELFT>::Got->addEntry(Body);
>        }
>      }
> -    if (canBePreempted(Body)) {
> +
> +    bool CBP = canBePreempted(Body);
> +    if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
> +      continue;
> +    if (CBP)
>        Body->setUsedInDynamicReloc();
> -      Out<ELFT>::RelaDyn->addReloc({C, RI});
> -    } else if (Config->Shared && !Target->isRelRelative(Type)) {
> -      Out<ELFT>::RelaDyn->addReloc({C, RI});
> -    }
> +    Out<ELFT>::RelaDyn->addReloc({C, RI});
>    }
>  }
>
>
> Added: lld/trunk/test/elf2/Inputs/shared2.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/shared2.s?rev=249998&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/Inputs/shared2.s (added)
> +++ lld/trunk/test/elf2/Inputs/shared2.s Sun Oct 11 15:59:12 2015
> @@ -0,0 +1,6 @@
> +.global bar2
> +.type bar2, @function
> +bar2:
> +
> +.global zed2
> +zed2:
>
> Added: lld/trunk/test/elf2/Inputs/shared3.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/shared3.s?rev=249998&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/Inputs/shared3.s (added)
> +++ lld/trunk/test/elf2/Inputs/shared3.s Sun Oct 11 15:59:12 2015
> @@ -0,0 +1,3 @@
> +.global baz
> +.type barz, @function
> +baz:
>
> Added: lld/trunk/test/elf2/as-needed.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/as-needed.s?rev=249998&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/as-needed.s (added)
> +++ lld/trunk/test/elf2/as-needed.s Sun Oct 11 15:59:12 2015
> @@ -0,0 +1,43 @@
> +// REQUIRES: x86
> +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
> +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
> +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared2.s -o %t3.o
> +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared3.s -o %t4.o
> +// RUN: ld.lld2 -shared %t2.o -soname shared1 -o %t2.so
> +// RUN: ld.lld2 -shared %t3.o -soname shared2 -o %t3.so
> +// RUN: ld.lld2 -shared %t4.o -soname shared3 -o %t4.so
> +
> +/// Check if --as-needed actually works.
> +
> +// RUN: ld.lld2 %t.o %t2.so %t3.so %t4.so -o %t2
> +// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
> +
> +// RUN: ld.lld2 --as-needed %t.o %t2.so %t3.so %t4.so -o %t2
> +// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
> +
> +// RUN: ld.lld2 --as-needed %t.o %t2.so --no-as-needed %t3.so %t4.so -o %t2
> +// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
> +
> +/// GROUP directive is the same as --as-needed.
> +
> +// RUN: echo "GROUP(" %t2.so %t3.so %t4.so ")" > %t.script
> +// RUN: ld.lld2 %t.o %t.script -o %t2
> +// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
> +
> +// RUN: echo "GROUP(AS_NEEDED(" %t2.so %t3.so %t4.so "))" > %t.script
> +// RUN: ld.lld2 %t.o %t.script -o %t2
> +// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
> +
> +// CHECK: NEEDED SharedLibrary (shared1)
> +// CHECK: NEEDED SharedLibrary (shared2)
> +// CHECK: NEEDED SharedLibrary (shared3)
> +
> +// CHECK2:     NEEDED SharedLibrary (shared1)
> +// CHECK2-NOT: NEEDED SharedLibrary (shared2)
> +// CHECK2-NOT: NEEDED SharedLibrary (shared3)
> +
> +.global _start
> +_start:
> +.long bar
> +.long zed
> +.weak baz
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list