[lld] r248854 - Start adding support for static programs using dynamic libraries.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 29 16:22:16 PDT 2015
Author: rafael
Date: Tue Sep 29 18:22:16 2015
New Revision: 248854
URL: http://llvm.org/viewvc/llvm-project?rev=248854&view=rev
Log:
Start adding support for static programs using dynamic libraries.
This is just enough for a hello world using a dynamic glibc.
Modified:
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Target.h
lld/trunk/ELF/Writer.cpp
lld/trunk/test/elf2/relocation.s
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Sep 29 18:22:16 2015
@@ -52,10 +52,10 @@ void InputSection<ELFT>::relocate(
const auto &Body =
*cast<ELFSymbolBody<ELFT>>(File.getSymbolBody(SymIndex));
SymVA = getSymVA<ELFT>(Body, BssSec);
- if (Target->relocNeedsPlt(Type)) {
+ if (Target->relocNeedsPlt(Type, Body)) {
SymVA = PltSec.getEntryAddr(Body);
Type = Target->getPCRelReloc();
- } else if (Target->relocNeedsGot(Type)) {
+ } else if (Target->relocNeedsGot(Type, Body)) {
SymVA = GotSec.getEntryAddr(Body);
Type = Target->getGotRefReloc();
} else if (Target->relocPointsToGot(Type)) {
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Sep 29 18:22:16 2015
@@ -104,7 +104,7 @@ template <class ELFT> void RelocationSec
uint32_t SymIndex = RI.getSymbol(IsMips64EL);
const SymbolBody *Body = C.getFile()->getSymbolBody(SymIndex);
uint32_t Type = RI.getType(IsMips64EL);
- if (Target->relocNeedsGot(Type)) {
+ if (Target->relocNeedsGot(Type, *Body)) {
P->r_offset = GotSec.getEntryAddr(*Body);
P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
Target->getGotReloc(), IsMips64EL);
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Tue Sep 29 18:22:16 2015
@@ -9,6 +9,7 @@
#include "Target.h"
#include "Error.h"
+#include "Symbols.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/ELF.h"
@@ -44,8 +45,8 @@ void X86TargetInfo::writePltEntry(uint8_
write32le(Buf + 2, GotEntryAddr);
}
-bool X86TargetInfo::relocNeedsGot(uint32_t Type) const {
- if (relocNeedsPlt(Type))
+bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ if (relocNeedsPlt(Type, S))
return true;
switch (Type) {
default:
@@ -59,7 +60,7 @@ bool X86TargetInfo::relocPointsToGot(uin
return Type == R_386_GOTPC;
}
-bool X86TargetInfo::relocNeedsPlt(uint32_t Type) const {
+bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
switch (Type) {
default:
return false;
@@ -112,8 +113,8 @@ void X86_64TargetInfo::writePltEntry(uin
write32le(Buf + 2, Delta);
}
-bool X86_64TargetInfo::relocNeedsGot(uint32_t Type) const {
- if (relocNeedsPlt(Type))
+bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ if (relocNeedsPlt(Type, S))
return true;
switch (Type) {
default:
@@ -123,10 +124,28 @@ bool X86_64TargetInfo::relocNeedsGot(uin
}
}
-bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type) const {
+bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
switch (Type) {
default:
return false;
+ case R_X86_64_PC32:
+ // This relocation is defined to have a value of (S + A - P).
+ // The problems start when a non PIC program calls a function is a shared
+ // library.
+ // In an idea world, we could just report an error saying the relocation
+ // can overflow at runtime.
+ // In the real world, crt1.o has a R_X86_64_PC32 pointing to libc.so.
+ // The general idea is to create a PLT entry and use that as the function
+ // value, which is why we return true in here.
+ // The remaining (unimplemented) problem is making sure pointer equality
+ // still works. For that, we need the help of the dynamic linker. We
+ // let it know that we have a direct reference to a symbol by creating
+ // an undefined symbol with a non zero st_value. Seeing that the
+ // dynamic linker resolves the symbol to the value of the symbol we created.
+ // This is true even for got entries, so pointer equality is maintained.
+ // To avoid an infinite loop, the only entry that points to the
+ // real function is a dedicated got entry used by the plt.
+ return S.isShared();
case R_X86_64_PLT32:
return true;
}
@@ -171,8 +190,12 @@ PPC64TargetInfo::PPC64TargetInfo() {
}
void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
-bool PPC64TargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
-bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool PPC64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
void PPC64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const {
@@ -200,8 +223,12 @@ PPCTargetInfo::PPCTargetInfo() {
}
void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
-bool PPCTargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
-bool PPCTargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
void PPCTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const {}
@@ -212,8 +239,12 @@ ARMTargetInfo::ARMTargetInfo() {
}
void ARMTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
-bool ARMTargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
-bool ARMTargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool ARMTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+bool ARMTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
void ARMTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const {}
@@ -224,8 +255,14 @@ AArch64TargetInfo::AArch64TargetInfo() {
}
void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
-bool AArch64TargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
-bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
+ const SymbolBody &S) const {
+ return false;
+}
+bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
+ const SymbolBody &S) const {
+ return false;
+}
static void handle_ADR_PREL_LO21(uint8_t *Location, uint64_t S, int64_t A,
uint64_t P) {
@@ -268,9 +305,13 @@ MipsTargetInfo::MipsTargetInfo() {
void MipsTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
-bool MipsTargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
+bool MipsTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
-bool MipsTargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool MipsTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
void MipsTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Tue Sep 29 18:22:16 2015
@@ -26,9 +26,9 @@ public:
unsigned getGotRefReloc() const { return GotRefReloc; };
virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const = 0;
- virtual bool relocNeedsGot(uint32_t Type) const = 0;
+ virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
virtual bool relocPointsToGot(uint32_t Type) const;
- virtual bool relocNeedsPlt(uint32_t Type) const = 0;
+ virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
virtual void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const = 0;
@@ -47,9 +47,9 @@ public:
X86TargetInfo();
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
- bool relocNeedsGot(uint32_t Type) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
bool relocPointsToGot(uint32_t Type) const override;
- bool relocNeedsPlt(uint32_t Type) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const override;
@@ -60,8 +60,8 @@ public:
X86_64TargetInfo();
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
- bool relocNeedsGot(uint32_t Type) const override;
- bool relocNeedsPlt(uint32_t Type) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const override;
@@ -72,8 +72,8 @@ public:
PPC64TargetInfo();
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
- bool relocNeedsGot(uint32_t Type) const override;
- bool relocNeedsPlt(uint32_t Type) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const override;
@@ -84,8 +84,8 @@ public:
PPCTargetInfo();
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
- bool relocNeedsGot(uint32_t Type) const override;
- bool relocNeedsPlt(uint32_t Type) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const override;
@@ -96,8 +96,8 @@ public:
ARMTargetInfo();
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
- bool relocNeedsGot(uint32_t Type) const override;
- bool relocNeedsPlt(uint32_t Type) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const override;
@@ -108,8 +108,8 @@ public:
AArch64TargetInfo();
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
- bool relocNeedsGot(uint32_t Type) const override;
- bool relocNeedsPlt(uint32_t Type) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const override;
@@ -120,8 +120,8 @@ public:
MipsTargetInfo();
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
- bool relocNeedsGot(uint32_t Type) const override;
- bool relocNeedsPlt(uint32_t Type) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA,
uint64_t GotVA) const override;
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Sep 29 18:22:16 2015
@@ -234,12 +234,12 @@ void Writer<ELFT>::scanRelocs(
if (!Body)
continue;
uint32_t Type = RI.getType(IsMips64EL);
- if (Target->relocNeedsPlt(Type)) {
+ if (Target->relocNeedsPlt(Type, *Body)) {
if (Body->isInPlt())
continue;
PltSec.addEntry(Body);
}
- if (Target->relocNeedsGot(Type)) {
+ if (Target->relocNeedsGot(Type, *Body)) {
if (Body->isInGot())
continue;
GotSec.addEntry(Body);
Modified: lld/trunk/test/elf2/relocation.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/relocation.s?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/test/elf2/relocation.s (original)
+++ lld/trunk/test/elf2/relocation.s Tue Sep 29 18:22:16 2015
@@ -1,7 +1,9 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
-// RUN: lld -flavor gnu2 %t -o %t2
-// RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=SEC %s
-// RUN: llvm-objdump -s -d %t2 | FileCheck %s
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2
+// RUN: lld -flavor gnu2 %t2 -o %t2.so -shared
+// RUN: lld -flavor gnu2 %t %t2.so -o %t3
+// RUN: llvm-readobj -s %t3 | FileCheck --check-prefix=SEC %s
+// RUN: llvm-objdump -s -d %t3 | FileCheck %s
// REQUIRES: x86
// SEC: Name: .got
@@ -10,15 +12,25 @@
// SEC-NEXT: SHF_ALLOC
// SEC-NEXT: SHF_WRITE
// SEC-NEXT: ]
-// SEC-NEXT: Address: 0x13000
+// SEC-NEXT: Address: 0x15000
// SEC-NEXT: Offset:
-// SEC-NEXT: Size: 8
+// SEC-NEXT: Size: 16
// SEC-NEXT: Link: 0
// SEC-NEXT: Info: 0
// SEC-NEXT: AddressAlignment: 8
// SEC-NEXT: EntrySize: 0
// SEC-NEXT: }
+// SEC: Name: .plt
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT: SHF_ALLOC
+// SEC-NEXT: SHF_EXECINSTR
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x16000
+// SEC-NEXT: Offset: 0x6000
+// SEC-NEXT: Size: 8
+
.section .text,"ax", at progbits,unique,1
.global _start
_start:
@@ -59,6 +71,15 @@ R_X86_64_32S:
// CHECK-NEXT: R_X86_64_32S:
// CHECK-NEXT: {{.*}}: {{.*}} movq -978935, %rdx
+.section .R_X86_64_PC32,"ax", at progbits
+.global R_X86_64_PC32
+R_X86_64_PC32:
+ call bar
+// 0x16000 - (0x11019 + 5) = 20450
+// CHECK: Disassembly of section .R_X86_64_PC32:
+// CHECK-NEXT: R_X86_64_PC32:
+// CHECK-NEXT: 11019: e8 e2 4f 00 00 callq 20450
+
.section .R_X86_64_64,"a", at progbits
.global R_X86_64_64
R_X86_64_64:
@@ -72,7 +93,7 @@ R_X86_64_64:
R_X86_64_GOTPCREL:
.long R_X86_64_GOTPCREL at gotpcrel
-// 0x13000 - 0x12008 = 4088
-// 4088 = 0xf80f0000 in little endian
+// 0x15008 - 0x12008 = 12288
+// 12288 = 0x00300000 in little endian
// CHECK: Contents of section .R_X86_64_GOTPCREL
-// CHECK-NEXT: 12008 f80f0000
+// CHECK-NEXT: 12008 00300000
More information about the llvm-commits
mailing list