[lld] r248308 - Start adding target abstractions.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 11:19:46 PDT 2015
Author: rafael
Date: Tue Sep 22 13:19:46 2015
New Revision: 248308
URL: http://llvm.org/viewvc/llvm-project?rev=248308&view=rev
Log:
Start adding target abstractions.
This is just enough to get PLT working on 32 bit x86.
The idea behind using a virtual interface is that it should be easy to
convert any of the functions to template parameters if any turns out to be
performance critical.
Added:
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Target.h
lld/trunk/test/elf2/plt-i686.s
Modified:
lld/trunk/ELF/CMakeLists.txt
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/SymbolTable.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=248308&r1=248307&r2=248308&view=diff
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt Tue Sep 22 13:19:46 2015
@@ -11,6 +11,7 @@ add_llvm_library(lldELF2
OutputSections.cpp
SymbolTable.cpp
Symbols.cpp
+ Target.cpp
Writer.cpp
LINK_COMPONENTS
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=248308&r1=248307&r2=248308&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Sep 22 13:19:46 2015
@@ -11,6 +11,7 @@
#include "Error.h"
#include "InputFiles.h"
#include "OutputSections.h"
+#include "Target.h"
#include "llvm/Support/raw_ostream.h"
@@ -114,12 +115,12 @@ void InputSection<ELFT>::relocate(
break;
}
case SymbolBody::SharedKind:
- if (relocNeedsPLT(Type)) {
+ if (Target->relocNeedsPlt(Type)) {
SymVA = PltSec.getEntryAddr(*Body);
- Type = R_X86_64_PC32;
- } else if (relocNeedsGOT(Type)) {
+ Type = Target->getPCRelReloc();
+ } else if (Target->relocNeedsGot(Type)) {
SymVA = GotSec.getEntryAddr(*Body);
- Type = R_X86_64_PC32;
+ Type = Target->getPCRelReloc();
} else {
continue;
}
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=248308&r1=248307&r2=248308&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Sep 22 13:19:46 2015
@@ -10,6 +10,7 @@
#include "OutputSections.h"
#include "Config.h"
#include "SymbolTable.h"
+#include "Target.h"
using namespace llvm;
using namespace llvm::object;
@@ -42,21 +43,11 @@ template <class ELFT> void PltSection<EL
uintptr_t Start = reinterpret_cast<uintptr_t>(Buf);
ArrayRef<uint8_t> Jmp = {0xff, 0x25}; // jmpq *val(%rip)
for (const SymbolBody *E : Entries) {
+ uint64_t GotEntryAddr = GotSec.getEntryAddr(*E);
uintptr_t InstPos = reinterpret_cast<uintptr_t>(Buf);
-
- memcpy(Buf, Jmp.data(), Jmp.size());
- Buf += Jmp.size();
-
- uintptr_t OffsetInPLT = (InstPos + 6) - Start;
- intptr_t Delta = GotSec.getEntryAddr(*E) - (this->getVA() + OffsetInPLT);
- assert(isInt<32>(Delta));
- support::endian::write32le(Buf, Delta);
- Buf += 4;
-
- *Buf = 0x90; // nop
- ++Buf;
- *Buf = 0x90; // nop
- ++Buf;
+ uint64_t PltEntryAddr = (InstPos - Start) + this->getVA();
+ Target->writePltEntry(Buf, GotEntryAddr, PltEntryAddr);
+ Buf += 8;
}
}
@@ -71,26 +62,6 @@ PltSection<ELFT>::getEntryAddr(const Sym
return this->getVA() + B.getPltIndex() * EntrySize;
}
-bool lld::elf2::relocNeedsPLT(uint32_t Type) {
- switch (Type) {
- default:
- return false;
- case R_X86_64_PLT32:
- return true;
- }
-}
-
-bool lld::elf2::relocNeedsGOT(uint32_t Type) {
- if (relocNeedsPLT(Type))
- return true;
- switch (Type) {
- default:
- return false;
- case R_X86_64_GOTPCREL:
- return true;
- }
-}
-
template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
bool IsMips64EL = Relocs[0].C.getFile()->getObj()->isMips64EL();
@@ -104,7 +75,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 (relocNeedsGOT(Type)) {
+ if (Target->relocNeedsGot(Type)) {
P->r_offset = GotSec.getEntryAddr(*Body);
P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), R_X86_64_GLOB_DAT,
IsMips64EL);
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=248308&r1=248307&r2=248308&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Tue Sep 22 13:19:46 2015
@@ -29,9 +29,6 @@ template <class ELFT> class OutputSectio
template <class ELFT> class ObjectFile;
template <class ELFT> class DefinedRegular;
-bool relocNeedsPLT(uint32_t Type);
-bool relocNeedsGOT(uint32_t Type);
-
template <class ELFT>
typename llvm::object::ELFFile<ELFT>::uintX_t
getSymVA(const DefinedRegular<ELFT> *DR);
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=248308&r1=248307&r2=248308&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Sep 22 13:19:46 2015
@@ -11,9 +11,11 @@
#include "Config.h"
#include "Error.h"
#include "Symbols.h"
+#include "Target.h"
using namespace llvm;
using namespace llvm::object;
+using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
@@ -37,7 +39,11 @@ void SymbolTable::addFile(std::unique_pt
addELFFile(cast<ELFFileBase>(FileP));
}
-template <class ELFT> void SymbolTable::init() {
+template <class ELFT> void SymbolTable::init(uint16_t EMachine) {
+ if (EMachine == EM_X86_64)
+ Target.reset(new X86_64TargetInfo());
+ else
+ Target.reset(new X86TargetInfo());
if (Config->Shared)
return;
EntrySym = new (Alloc) Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic);
@@ -49,7 +55,7 @@ template <class ELFT> void SymbolTable::
if (!Old->isCompatibleWith(*File))
error(Twine(Old->getName() + " is incompatible with " + File->getName()));
} else {
- init<ELFT>();
+ init<ELFT>(File->getEMachine());
}
if (auto *O = dyn_cast<ObjectFileBase>(File)) {
Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=248308&r1=248307&r2=248308&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Tue Sep 22 13:19:46 2015
@@ -68,7 +68,7 @@ private:
void addLazy(Lazy *New);
void addMemberFile(Lazy *Body);
- template <class ELFT> void init();
+ template <class ELFT> void init(uint16_t EMachine);
template <class ELFT> void resolve(SymbolBody *Body);
std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
Added: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=248308&view=auto
==============================================================================
--- lld/trunk/ELF/Target.cpp (added)
+++ lld/trunk/ELF/Target.cpp Tue Sep 22 13:19:46 2015
@@ -0,0 +1,100 @@
+//===- Target.cpp ---------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Target.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ELF.h"
+
+using namespace llvm;
+using namespace llvm::ELF;
+
+namespace lld {
+namespace elf2 {
+
+std::unique_ptr<TargetInfo> Target;
+
+TargetInfo::~TargetInfo() {}
+
+X86TargetInfo::X86TargetInfo() { PCRelReloc = R_386_PC32; }
+
+void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const {
+ ArrayRef<uint8_t> Jmp = {0xff, 0x25}; // jmpl *val
+ memcpy(Buf, Jmp.data(), Jmp.size());
+ Buf += Jmp.size();
+
+ assert(isUInt<32>(GotEntryAddr));
+ support::endian::write32le(Buf, GotEntryAddr);
+ Buf += 4;
+
+ ArrayRef<uint8_t> Nops = {0x90, 0x90};
+ memcpy(Buf, Nops.data(), Nops.size());
+}
+
+bool X86TargetInfo::relocNeedsGot(uint32_t Type) const {
+ if (relocNeedsPlt(Type))
+ return true;
+ switch (Type) {
+ default:
+ return false;
+ case R_386_GOT32:
+ return true;
+ }
+}
+
+bool X86TargetInfo::relocNeedsPlt(uint32_t Type) const {
+ switch (Type) {
+ default:
+ return false;
+ case R_386_PLT32:
+ return true;
+ }
+}
+
+X86_64TargetInfo::X86_64TargetInfo() { PCRelReloc = R_X86_64_PC32; }
+
+void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const {
+ ArrayRef<uint8_t> Jmp = {0xff, 0x25}; // jmpq *val(%rip)
+ memcpy(Buf, Jmp.data(), Jmp.size());
+ Buf += Jmp.size();
+
+ uintptr_t NextPC = PltEntryAddr + 6;
+ uintptr_t Delta = GotEntryAddr - NextPC;
+ assert(isInt<32>(Delta));
+ support::endian::write32le(Buf, Delta);
+ Buf += 4;
+
+ ArrayRef<uint8_t> Nops = {0x90, 0x90};
+ memcpy(Buf, Nops.data(), Nops.size());
+}
+
+bool X86_64TargetInfo::relocNeedsGot(uint32_t Type) const {
+ if (relocNeedsPlt(Type))
+ return true;
+ switch (Type) {
+ default:
+ return false;
+ case R_X86_64_GOTPCREL:
+ return true;
+ }
+}
+
+bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type) const {
+ switch (Type) {
+ default:
+ return false;
+ case R_X86_64_PLT32:
+ return true;
+ }
+}
+}
+}
Added: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=248308&view=auto
==============================================================================
--- lld/trunk/ELF/Target.h (added)
+++ lld/trunk/ELF/Target.h Tue Sep 22 13:19:46 2015
@@ -0,0 +1,54 @@
+//===- Target.h -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_TARGET_H
+#define LLD_ELF_TARGET_H
+
+#include <memory>
+
+namespace lld {
+namespace elf2 {
+class SymbolBody;
+
+class TargetInfo {
+public:
+ unsigned getPCRelReloc() const { return PCRelReloc; }
+ virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const = 0;
+ virtual bool relocNeedsGot(uint32_t Type) const = 0;
+ virtual bool relocNeedsPlt(uint32_t Type) const = 0;
+ virtual ~TargetInfo();
+
+protected:
+ unsigned PCRelReloc;
+};
+
+class X86TargetInfo final : public TargetInfo {
+public:
+ X86TargetInfo();
+ 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;
+};
+
+class X86_64TargetInfo final : public TargetInfo {
+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;
+};
+
+extern std::unique_ptr<TargetInfo> Target;
+}
+}
+
+#endif
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=248308&r1=248307&r2=248308&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Sep 22 13:19:46 2015
@@ -11,6 +11,7 @@
#include "Config.h"
#include "OutputSections.h"
#include "SymbolTable.h"
+#include "Target.h"
#include "llvm/Support/FileOutputBuffer.h"
@@ -256,12 +257,12 @@ void Writer<ELFT>::scanRelocs(
if (!S)
continue;
uint32_t Type = RI.getType(IsMips64EL);
- if (relocNeedsPLT(Type)) {
+ if (Target->relocNeedsPlt(Type)) {
if (Body->isInPlt())
continue;
PltSec.addEntry(Body);
}
- if (relocNeedsGOT(Type)) {
+ if (Target->relocNeedsGot(Type)) {
if (Body->isInGot())
continue;
GotSec.addEntry(Body);
Added: lld/trunk/test/elf2/plt-i686.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/plt-i686.s?rev=248308&view=auto
==============================================================================
--- lld/trunk/test/elf2/plt-i686.s (added)
+++ lld/trunk/test/elf2/plt-i686.s Tue Sep 22 13:19:46 2015
@@ -0,0 +1,57 @@
+// 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: lld -flavor gnu2 -shared %t2.o -o %t2.so
+// RUN: lld -flavor gnu2 %t.o %t2.so -o %t
+// RUN: llvm-readobj -s -r %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+// REQUIRES: x86
+
+// CHECK: Name: .plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x16000
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 16
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rel.dyn {
+// CHECK-NEXT: 0x15000 R_386_GLOB_DAT bar 0x0
+// CHECK-NEXT: 0x15004 R_386_GLOB_DAT zed 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// Unfortunately FileCheck can't do math, so we have to check for explicit
+// values:
+
+// 0x16000 - (0x11000 + 1) - 4 = 20475
+// 0x16000 - (0x11005 + 1) - 4 = 20470
+// 0x16008 - (0x1100a + 1) - 4 = 20473
+
+// DISASM: _start:
+// DISASM-NEXT: 11000: e9 fb 4f 00 00 jmp 20475
+// DISASM-NEXT: 11005: e9 f6 4f 00 00 jmp 20470
+// DISASM-NEXT: 1100a: e9 f9 4f 00 00 jmp 20473
+
+// 0x15000 = 86016
+// 0x15004 = 86020
+
+// DISASM: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT: 16000: ff 25 00 50 01 00 jmpl *86016
+// DISASM-NEXT: 16006: 90 nop
+// DISASM-NEXT: 16007: 90 nop
+// DISASM-NEXT: 16008: ff 25 04 50 01 00 jmpl *86020
+// DISASM-NEXT: 1600e: 90 nop
+// DISASM-NEXT: 1600f: 90 nop
+
+.global _start
+_start:
+ jmp bar at PLT
+ jmp bar at PLT
+ jmp zed at PLT
More information about the llvm-commits
mailing list