<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>