<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Feb 9, 2016 at 7:11 AM, Rafael Espindola via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rafael<br>
Date: Tue Feb  9 09:11:01 2016<br>
New Revision: 260224<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=260224&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=260224&view=rev</a><br>
Log:<br>
Use the plt entry as the address of some symbols.<br>
<br>
This is the function equivalent of a copy relocation.<br>
<br>
Since functions are expected to change sizes, we cannot use copy<br>
relocations. In situations where one would be needed, what is done<br>
instead is:<br>
* Create a plt entry<br>
* Output an undefined symbol whose addr is the plt entry.<br>
<br>
The dynamic linker makes sure any shared library uses the plt entry as<br>
the function address.<br>
<br>
Added:<br>
    lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s<br>
    lld/trunk/test/ELF/undef-with-plt-addr.s<br>
Modified:<br>
    lld/trunk/ELF/OutputSections.cpp<br>
    lld/trunk/ELF/Symbols.cpp<br>
    lld/trunk/ELF/Symbols.h<br>
    lld/trunk/ELF/Target.cpp<br>
    lld/trunk/ELF/Target.h<br>
    lld/trunk/ELF/Writer.cpp<br>
    lld/trunk/test/ELF/symbol-override.s<br>
<br>
Modified: lld/trunk/ELF/OutputSections.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=260224&r1=260223&r2=260224&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=260224&r1=260223&r2=260224&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/OutputSections.cpp (original)<br>
+++ lld/trunk/ELF/OutputSections.cpp Tue Feb  9 09:11:01 2016<br>
@@ -1328,7 +1328,7 @@ void SymbolTableSection<ELFT>::writeGlob<br>
       OutSec = Out<ELFT>::Bss;<br>
       break;<br>
     case SymbolBody::SharedKind: {<br>
-      if (cast<SharedSymbol<ELFT>>(Body)->NeedsCopy)<br>
+      if (cast<SharedSymbol<ELFT>>(Body)->needsCopy())<br>
         OutSec = Out<ELFT>::Bss;<br>
       break;<br>
     }<br>
<br>
Modified: lld/trunk/ELF/Symbols.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=260224&r1=260223&r2=260224&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=260224&r1=260223&r2=260224&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Symbols.cpp (original)<br>
+++ lld/trunk/ELF/Symbols.cpp Tue Feb  9 09:11:01 2016<br>
@@ -56,9 +56,12 @@ typename ELFFile<ELFT>::uintX_t SymbolBo<br>
     return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(this)->OffsetInBss;<br>
   case SharedKind: {<br>
     auto *SS = cast<SharedSymbol<ELFT>>(this);<br>
-    if (SS->NeedsCopy)<br>
+    if (!SS->NeedsCopyOrPltAddr)<br>
+      return 0;<br>
+    if (SS->IsFunc)<br>
+      return getPltVA<ELFT>();<br>
+    else<br>
       return Out<ELFT>::Bss->getVA() + SS->OffsetInBss;<br>
-    return 0;<br>
   }<br>
   case UndefinedElfKind:<br>
   case UndefinedKind:<br>
<br>
Modified: lld/trunk/ELF/Symbols.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=260224&r1=260223&r2=260224&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=260224&r1=260223&r2=260224&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Symbols.h (original)<br>
+++ lld/trunk/ELF/Symbols.h Tue Feb  9 09:11:01 2016<br>
@@ -130,7 +130,8 @@ protected:<br>
   SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,<br>
              bool IsTls, bool IsFunc)<br>
       : SymbolKind(K), IsWeak(IsWeak), Visibility(Visibility),<br>
-        MustBeInDynSym(false), IsTls(IsTls), IsFunc(IsFunc), Name(Name) {<br>
+        MustBeInDynSym(false), NeedsCopyOrPltAddr(false), IsTls(IsTls),<br>
+        IsFunc(IsFunc), Name(Name) {<br>
     IsUsedInRegularObj = K != SharedKind && K != LazyKind;<br>
   }<br>
<br>
@@ -148,9 +149,14 @@ public:<br>
   // If true, the symbol is added to .dynsym symbol table.<br>
   unsigned MustBeInDynSym : 1;<br>
<br>
+  // True if the linker has to generate a copy relocation for this shared<br>
+  // symbol or if the symbol should point to its plt entry.<br>
+  unsigned NeedsCopyOrPltAddr : 1;<br>
+<br>
 protected:<br>
   unsigned IsTls : 1;<br>
   unsigned IsFunc : 1;<br>
+<br>
   StringRef Name;<br>
   Symbol *Backref = nullptr;<br>
 };<br>
@@ -280,10 +286,10 @@ public:<br>
<br>
   SharedFile<ELFT> *File;<br>
<br>
-  // True if the linker has to generate a copy relocation for this shared<br>
-  // symbol. OffsetInBss is significant only when NeedsCopy is true.<br>
-  bool NeedsCopy = false;<br>
+  // OffsetInBss is significant only when needsCopy() is true.<br>
   uintX_t OffsetInBss = 0;<br>
+<br>
+  bool needsCopy() const { return this->NeedsCopyOrPltAddr && !this->IsFunc; }<br>
 };<br>
<br>
 // This class represents a symbol defined in an archive file. It is<br>
<br>
Modified: lld/trunk/ELF/Target.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=260224&r1=260223&r2=260224&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=260224&r1=260223&r2=260224&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Target.cpp (original)<br>
+++ lld/trunk/ELF/Target.cpp Tue Feb  9 09:11:01 2016<br>
@@ -90,8 +90,8 @@ public:<br>
                 int32_t Index, unsigned RelOff) const override;<br>
   bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;<br>
   bool needsDynRelative(unsigned Type) const override;<br>
-  bool needsGot(uint32_t Type, const SymbolBody &S) const override;<br>
-  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;<br>
+  bool needsGot(uint32_t Type, SymbolBody &S) const override;<br>
+  bool needsPlt(uint32_t Type, SymbolBody &S) const override;<br>
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,<br>
                    uint64_t SA, uint64_t ZA = 0,<br>
                    uint8_t *PairedLoc = nullptr) const override;<br>
@@ -121,8 +121,8 @@ public:<br>
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,<br>
                 int32_t Index, unsigned RelOff) const override;<br>
   bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;<br>
-  bool needsGot(uint32_t Type, const SymbolBody &S) const override;<br>
-  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;<br>
+  bool needsGot(uint32_t Type, SymbolBody &S) const override;<br>
+  bool needsPlt(uint32_t Type, SymbolBody &S) const override;<br>
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,<br>
                    uint64_t SA, uint64_t ZA = 0,<br>
                    uint8_t *PairedLoc = nullptr) const override;<br>
@@ -157,8 +157,8 @@ public:<br>
   PPC64TargetInfo();<br>
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,<br>
                 int32_t Index, unsigned RelOff) const override;<br>
-  bool needsGot(uint32_t Type, const SymbolBody &S) const override;<br>
-  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;<br>
+  bool needsGot(uint32_t Type, SymbolBody &S) const override;<br>
+  bool needsPlt(uint32_t Type, SymbolBody &S) const override;<br>
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,<br>
                    uint64_t SA, uint64_t ZA = 0,<br>
                    uint8_t *PairedLoc = nullptr) const override;<br>
@@ -176,8 +176,8 @@ public:<br>
   unsigned getTlsGotRel(unsigned Type = -1) const override;<br>
   bool isTlsDynRel(unsigned Type, const SymbolBody &S) const override;<br>
   bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;<br>
-  bool needsGot(uint32_t Type, const SymbolBody &S) const override;<br>
-  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;<br>
+  bool needsGot(uint32_t Type, SymbolBody &S) const override;<br>
+  bool needsPlt(uint32_t Type, SymbolBody &S) const override;<br>
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,<br>
                    uint64_t SA, uint64_t ZA = 0,<br>
                    uint8_t *PairedLoc = nullptr) const override;<br>
@@ -197,8 +197,8 @@ public:<br>
   unsigned getDynRel(unsigned Type) const override;<br>
   void writeGotHeader(uint8_t *Buf) const override;<br>
   bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;<br>
-  bool needsGot(uint32_t Type, const SymbolBody &S) const override;<br>
-  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;<br>
+  bool needsGot(uint32_t Type, SymbolBody &S) const override;<br>
+  bool needsPlt(uint32_t Type, SymbolBody &S) const override;<br>
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,<br>
                    uint64_t SA, uint64_t ZA = 0,<br>
                    uint8_t *PairedLoc = nullptr) const override;<br>
@@ -263,13 +263,9 @@ bool TargetInfo::isHintRel(uint32_t Type<br>
 bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }<br>
 bool TargetInfo::isSizeRel(uint32_t Type) const { return false; }<br>
<br>
-bool TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {<br>
-  return false;<br>
-}<br>
+bool TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const { return false; }<br>
<br>
-bool TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {<br>
-  return false;<br>
-}<br>
+bool TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { return false; }<br>
<br>
 unsigned TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,<br>
                               uint64_t P, uint64_t SA,<br>
@@ -376,7 +372,7 @@ bool X86TargetInfo::needsCopyRel(uint32_<br>
   return false;<br>
 }<br>
<br>
-bool X86TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {<br>
+bool X86TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {<br>
   if (S.isTls() && Type == R_386_TLS_GD)<br>
     return Target->canRelaxTls(Type, &S) && canBePreempted(&S, true);<br>
   if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)<br>
@@ -384,7 +380,7 @@ bool X86TargetInfo::needsGot(uint32_t Ty<br>
   return Type == R_386_GOT32 || needsPlt(Type, S);<br>
 }<br>
<br>
-bool X86TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {<br>
+bool X86TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const {<br>
   return isGnuIFunc<ELF32LE>(S) ||<br>
          (Type == R_386_PLT32 && canBePreempted(&S, true)) ||<br>
          (Type == R_386_PC32 && S.isShared());<br>
@@ -646,7 +642,7 @@ bool X86_64TargetInfo::needsCopyRel(uint<br>
   return false;<br>
 }<br>
<br>
-bool X86_64TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {<br>
+bool X86_64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {<br>
   if (Type == R_X86_64_TLSGD)<br>
     return Target->canRelaxTls(Type, &S) && canBePreempted(&S, true);<br>
   if (Type == R_X86_64_GOTTPOFF)<br>
@@ -658,7 +654,7 @@ bool X86_64TargetInfo::isTlsDynRel(unsig<br>
   return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;<br>
 }<br>
<br>
-bool X86_64TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {<br>
+bool X86_64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const {<br>
   if (needsCopyRel(Type, S))<br>
     return false;<br>
   if (isGnuIFunc<ELF64LE>(S))<br>
@@ -684,17 +680,19 @@ bool X86_64TargetInfo::needsPlt(uint32_t<br>
     // For the static linking part, we just return true and everything else<br>
     // will use the the PLT entry as the address.<br>
     //<br>
-    // The remaining (unimplemented) problem is making sure pointer equality<br>
-    // still works. We need the help of the dynamic linker for that. We<br>
-    // let it know that we have a direct reference to a so symbol by creating<br>
-    // an undefined symbol with a non zero st_value. Seeing that, the<br>
-    // dynamic linker resolves the symbol to the value of the symbol we created.<br>
-    // This is true even for got entries, so pointer equality is maintained.<br>
-    // To avoid an infinite loop, the only entry that points to the<br>
-    // real function is a dedicated got entry used by the plt. That is<br>
-    // identified by special relocation types (R_X86_64_JUMP_SLOT,<br>
+    // The remaining problem is making sure pointer equality still works. We<br>
+    // need the help of the dynamic linker for that. We let it know that we have<br>
+    // a direct reference to a so symbol by creating an undefined symbol with a<br>
+    // non zero st_value. Seeing that, the dynamic linker resolves the symbol to<br>
+    // the value of the symbol we created. This is true even for got entries, so<br>
+    // pointer equality is maintained. To avoid an infinite loop, the only entry<br>
+    // that points to the real function is a dedicated got entry used by the<br>
+    // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,<br>
     // R_386_JMP_SLOT, etc).<br>
-    return S.isShared();<br>
+    if (!S.isShared())<br>
+      return false;<br>
+    S.NeedsCopyOrPltAddr = true;<br></blockquote><div><br></div><div>Can you move this to a caller of needsPlt (probably to scanRelocs)? needsPlt is, by its name implies, a predicate, so it is not expected to mutate a given object.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    return true;<br>
   case R_X86_64_PLT32:<br>
     return canBePreempted(&S, true);<br>
   }<br>
@@ -989,7 +987,7 @@ void PPC64TargetInfo::writePlt(uint8_t *<br>
   write32be(Buf + 28, 0x4e800420);                   // bctr<br>
 }<br>
<br>
-bool PPC64TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {<br>
+bool PPC64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {<br>
   if (needsPlt(Type, S))<br>
     return true;<br>
<br>
@@ -1005,7 +1003,7 @@ bool PPC64TargetInfo::needsGot(uint32_t<br>
   }<br>
 }<br>
<br>
-bool PPC64TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {<br>
+bool PPC64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const {<br>
   // These are function calls that need to be redirected through a PLT stub.<br>
   return Type == R_PPC64_REL24 && canBePreempted(&S, false);<br>
 }<br>
@@ -1240,7 +1238,7 @@ bool AArch64TargetInfo::needsCopyRel(uin<br>
   }<br>
 }<br>
<br>
-bool AArch64TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {<br>
+bool AArch64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {<br>
   switch (Type) {<br>
   case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:<br>
   case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:<br>
@@ -1252,7 +1250,7 @@ bool AArch64TargetInfo::needsGot(uint32_<br>
   }<br>
 }<br>
<br>
-bool AArch64TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {<br>
+bool AArch64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const {<br>
   if (isGnuIFunc<ELF64LE>(S))<br>
     return true;<br>
   switch (Type) {<br>
@@ -1439,12 +1437,12 @@ bool MipsTargetInfo<ELFT>::needsCopyRel(<br>
 }<br>
<br>
 template <class ELFT><br>
-bool MipsTargetInfo<ELFT>::needsGot(uint32_t Type, const SymbolBody &S) const {<br>
+bool MipsTargetInfo<ELFT>::needsGot(uint32_t Type, SymbolBody &S) const {<br>
   return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16;<br>
 }<br>
<br>
 template <class ELFT><br>
-bool MipsTargetInfo<ELFT>::needsPlt(uint32_t Type, const SymbolBody &S) const {<br>
+bool MipsTargetInfo<ELFT>::needsPlt(uint32_t Type, SymbolBody &S) const {<br>
   return false;<br>
 }<br>
<br>
<br>
Modified: lld/trunk/ELF/Target.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=260224&r1=260223&r2=260224&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=260224&r1=260223&r2=260224&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Target.h (original)<br>
+++ lld/trunk/ELF/Target.h Tue Feb  9 09:11:01 2016<br>
@@ -54,8 +54,8 @@ public:<br>
<br>
   virtual bool isSizeRel(uint32_t Type) const;<br>
   virtual bool needsDynRelative(unsigned Type) const { return false; }<br>
-  virtual bool needsGot(uint32_t Type, const SymbolBody &S) const;<br>
-  virtual bool needsPlt(uint32_t Type, const SymbolBody &S) const;<br>
+  virtual bool needsGot(uint32_t Type, SymbolBody &S) const;<br>
+  virtual bool needsPlt(uint32_t Type, SymbolBody &S) const;<br>
   virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,<br>
                            uint64_t P, uint64_t SA, uint64_t ZA = 0,<br>
                            uint8_t *PairedLoc = nullptr) const = 0;<br>
<br>
Modified: lld/trunk/ELF/Writer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=260224&r1=260223&r2=260224&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=260224&r1=260223&r2=260224&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Writer.cpp (original)<br>
+++ lld/trunk/ELF/Writer.cpp Tue Feb  9 09:11:01 2016<br>
@@ -302,10 +302,10 @@ void Writer<ELFT>::scanRelocs(<br>
     // If a symbol in a DSO is referenced directly instead of through GOT,<br>
     // we need to create a copy relocation for the symbol.<br>
     if (auto *B = dyn_cast_or_null<SharedSymbol<ELFT>>(Body)) {<br>
-      if (B->NeedsCopy)<br>
+      if (B->needsCopy())<br>
         continue;<br>
       if (Target->needsCopyRel(Type, *B)) {<br>
-        B->NeedsCopy = true;<br>
+        B->NeedsCopyOrPltAddr = true;<br>
         Out<ELFT>::RelaDyn->addReloc(<br>
             {Target->CopyRel, DynamicReloc<ELFT>::Off_Bss, B});<br>
         continue;<br>
@@ -968,7 +968,7 @@ template <class ELFT> bool Writer<ELFT>:<br>
     if (auto *C = dyn_cast<DefinedCommon>(Body))<br>
       CommonSymbols.push_back(C);<br>
     if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))<br>
-      if (SC->NeedsCopy)<br>
+      if (SC->needsCopy())<br>
         CopyRelSymbols.push_back(SC);<br>
<br>
     if (!includeInSymtab<ELFT>(*Body))<br>
<br>
Added: lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s?rev=260224&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s?rev=260224&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s (added)<br>
+++ lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s Tue Feb  9 09:11:01 2016<br>
@@ -0,0 +1,4 @@<br>
+       .globl  set_data<br>
+       .type   set_data,@function<br>
+set_data:<br>
+       retq<br>
<br>
Modified: lld/trunk/test/ELF/symbol-override.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/symbol-override.s?rev=260224&r1=260223&r2=260224&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/symbol-override.s?rev=260224&r1=260223&r2=260224&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/symbol-override.s (original)<br>
+++ lld/trunk/test/ELF/symbol-override.s Tue Feb  9 09:11:01 2016<br>
@@ -43,4 +43,4 @@ nop<br>
 .text<br>
 .globl _start<br>
 _start:<br>
-callq do<br>
+callq do@plt<br>
<br>
Added: lld/trunk/test/ELF/undef-with-plt-addr.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/undef-with-plt-addr.s?rev=260224&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/undef-with-plt-addr.s?rev=260224&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/undef-with-plt-addr.s (added)<br>
+++ lld/trunk/test/ELF/undef-with-plt-addr.s Tue Feb  9 09:11:01 2016<br>
@@ -0,0 +1,23 @@<br>
+// REQUIRES: x86<br>
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o<br>
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o<br>
+// RUN: ld.lld %t2.o -o %t2.so -shared<br>
+// RUN: ld.lld %t.o %t2.so -o %t3<br>
+// RUN: llvm-readobj -t -s %t3 | FileCheck %s<br>
+<br>
+.globl _start<br>
+_start:<br>
+movabsq        $set_data, %rax<br>
+<br>
+// Test that set_data has an address in the .plt<br>
+<br>
+// CHECK:      Name: .plt<br>
+// CHECK-NEXT: Type: SHT_PROGBITS<br>
+// CHECK-NEXT: Flags [<br>
+// CHECK-NEXT:   SHF_ALLOC<br>
+// CHECK-NEXT:   SHF_EXECINSTR<br>
+// CHECK-NEXT: ]<br>
+// CHECK-NEXT: Address: 0x11010<br>
+<br>
+// CHECK:      Name:    set_data<br>
+// CHECK-NEXT: Value:   0x11020<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>