forked from OSchip/llvm-project
				
			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. llvm-svn: 248308
This commit is contained in:
		
							parent
							
								
									e8fe34d4d1
								
							
						
					
					
						commit
						01205f79a4
					
				| 
						 | 
					@ -11,6 +11,7 @@ add_llvm_library(lldELF2
 | 
				
			||||||
  OutputSections.cpp
 | 
					  OutputSections.cpp
 | 
				
			||||||
  SymbolTable.cpp
 | 
					  SymbolTable.cpp
 | 
				
			||||||
  Symbols.cpp
 | 
					  Symbols.cpp
 | 
				
			||||||
 | 
					  Target.cpp
 | 
				
			||||||
  Writer.cpp
 | 
					  Writer.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  LINK_COMPONENTS
 | 
					  LINK_COMPONENTS
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@
 | 
				
			||||||
#include "Error.h"
 | 
					#include "Error.h"
 | 
				
			||||||
#include "InputFiles.h"
 | 
					#include "InputFiles.h"
 | 
				
			||||||
#include "OutputSections.h"
 | 
					#include "OutputSections.h"
 | 
				
			||||||
 | 
					#include "Target.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "llvm/Support/raw_ostream.h"
 | 
					#include "llvm/Support/raw_ostream.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,12 +115,12 @@ void InputSection<ELFT>::relocate(
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      case SymbolBody::SharedKind:
 | 
					      case SymbolBody::SharedKind:
 | 
				
			||||||
        if (relocNeedsPLT(Type)) {
 | 
					        if (Target->relocNeedsPlt(Type)) {
 | 
				
			||||||
          SymVA = PltSec.getEntryAddr(*Body);
 | 
					          SymVA = PltSec.getEntryAddr(*Body);
 | 
				
			||||||
          Type = R_X86_64_PC32;
 | 
					          Type = Target->getPCRelReloc();
 | 
				
			||||||
        } else if (relocNeedsGOT(Type)) {
 | 
					        } else if (Target->relocNeedsGot(Type)) {
 | 
				
			||||||
          SymVA = GotSec.getEntryAddr(*Body);
 | 
					          SymVA = GotSec.getEntryAddr(*Body);
 | 
				
			||||||
          Type = R_X86_64_PC32;
 | 
					          Type = Target->getPCRelReloc();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          continue;
 | 
					          continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
#include "OutputSections.h"
 | 
					#include "OutputSections.h"
 | 
				
			||||||
#include "Config.h"
 | 
					#include "Config.h"
 | 
				
			||||||
#include "SymbolTable.h"
 | 
					#include "SymbolTable.h"
 | 
				
			||||||
 | 
					#include "Target.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace llvm;
 | 
					using namespace llvm;
 | 
				
			||||||
using namespace llvm::object;
 | 
					using namespace llvm::object;
 | 
				
			||||||
| 
						 | 
					@ -42,21 +43,11 @@ template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
 | 
				
			||||||
  uintptr_t Start = reinterpret_cast<uintptr_t>(Buf);
 | 
					  uintptr_t Start = reinterpret_cast<uintptr_t>(Buf);
 | 
				
			||||||
  ArrayRef<uint8_t> Jmp = {0xff, 0x25}; // jmpq *val(%rip)
 | 
					  ArrayRef<uint8_t> Jmp = {0xff, 0x25}; // jmpq *val(%rip)
 | 
				
			||||||
  for (const SymbolBody *E : Entries) {
 | 
					  for (const SymbolBody *E : Entries) {
 | 
				
			||||||
 | 
					    uint64_t GotEntryAddr = GotSec.getEntryAddr(*E);
 | 
				
			||||||
    uintptr_t InstPos = reinterpret_cast<uintptr_t>(Buf);
 | 
					    uintptr_t InstPos = reinterpret_cast<uintptr_t>(Buf);
 | 
				
			||||||
 | 
					    uint64_t PltEntryAddr = (InstPos - Start) + this->getVA();
 | 
				
			||||||
    memcpy(Buf, Jmp.data(), Jmp.size());
 | 
					    Target->writePltEntry(Buf, GotEntryAddr, PltEntryAddr);
 | 
				
			||||||
    Buf += Jmp.size();
 | 
					    Buf += 8;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    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;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,26 +62,6 @@ PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
 | 
				
			||||||
  return this->getVA() + B.getPltIndex() * EntrySize;
 | 
					  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) {
 | 
					template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
 | 
				
			||||||
  const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
 | 
					  const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
 | 
				
			||||||
  bool IsMips64EL = Relocs[0].C.getFile()->getObj()->isMips64EL();
 | 
					  bool IsMips64EL = Relocs[0].C.getFile()->getObj()->isMips64EL();
 | 
				
			||||||
| 
						 | 
					@ -104,7 +75,7 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
 | 
				
			||||||
    uint32_t SymIndex = RI.getSymbol(IsMips64EL);
 | 
					    uint32_t SymIndex = RI.getSymbol(IsMips64EL);
 | 
				
			||||||
    const SymbolBody *Body = C.getFile()->getSymbolBody(SymIndex);
 | 
					    const SymbolBody *Body = C.getFile()->getSymbolBody(SymIndex);
 | 
				
			||||||
    uint32_t Type = RI.getType(IsMips64EL);
 | 
					    uint32_t Type = RI.getType(IsMips64EL);
 | 
				
			||||||
    if (relocNeedsGOT(Type)) {
 | 
					    if (Target->relocNeedsGot(Type)) {
 | 
				
			||||||
      P->r_offset = GotSec.getEntryAddr(*Body);
 | 
					      P->r_offset = GotSec.getEntryAddr(*Body);
 | 
				
			||||||
      P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), R_X86_64_GLOB_DAT,
 | 
					      P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), R_X86_64_GLOB_DAT,
 | 
				
			||||||
                          IsMips64EL);
 | 
					                          IsMips64EL);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,9 +29,6 @@ template <class ELFT> class OutputSection;
 | 
				
			||||||
template <class ELFT> class ObjectFile;
 | 
					template <class ELFT> class ObjectFile;
 | 
				
			||||||
template <class ELFT> class DefinedRegular;
 | 
					template <class ELFT> class DefinedRegular;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool relocNeedsPLT(uint32_t Type);
 | 
					 | 
				
			||||||
bool relocNeedsGOT(uint32_t Type);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template <class ELFT>
 | 
					template <class ELFT>
 | 
				
			||||||
typename llvm::object::ELFFile<ELFT>::uintX_t
 | 
					typename llvm::object::ELFFile<ELFT>::uintX_t
 | 
				
			||||||
getSymVA(const DefinedRegular<ELFT> *DR);
 | 
					getSymVA(const DefinedRegular<ELFT> *DR);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,9 +11,11 @@
 | 
				
			||||||
#include "Config.h"
 | 
					#include "Config.h"
 | 
				
			||||||
#include "Error.h"
 | 
					#include "Error.h"
 | 
				
			||||||
#include "Symbols.h"
 | 
					#include "Symbols.h"
 | 
				
			||||||
 | 
					#include "Target.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace llvm;
 | 
					using namespace llvm;
 | 
				
			||||||
using namespace llvm::object;
 | 
					using namespace llvm::object;
 | 
				
			||||||
 | 
					using namespace llvm::ELF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace lld;
 | 
					using namespace lld;
 | 
				
			||||||
using namespace lld::elf2;
 | 
					using namespace lld::elf2;
 | 
				
			||||||
| 
						 | 
					@ -37,7 +39,11 @@ void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
 | 
				
			||||||
  addELFFile(cast<ELFFileBase>(FileP));
 | 
					  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)
 | 
					  if (Config->Shared)
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  EntrySym = new (Alloc) Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic);
 | 
					  EntrySym = new (Alloc) Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic);
 | 
				
			||||||
| 
						 | 
					@ -49,7 +55,7 @@ template <class ELFT> void SymbolTable::addELFFile(ELFFileBase *File) {
 | 
				
			||||||
    if (!Old->isCompatibleWith(*File))
 | 
					    if (!Old->isCompatibleWith(*File))
 | 
				
			||||||
      error(Twine(Old->getName() + " is incompatible with " + File->getName()));
 | 
					      error(Twine(Old->getName() + " is incompatible with " + File->getName()));
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    init<ELFT>();
 | 
					    init<ELFT>(File->getEMachine());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (auto *O = dyn_cast<ObjectFileBase>(File)) {
 | 
					  if (auto *O = dyn_cast<ObjectFileBase>(File)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ private:
 | 
				
			||||||
  void addLazy(Lazy *New);
 | 
					  void addLazy(Lazy *New);
 | 
				
			||||||
  void addMemberFile(Lazy *Body);
 | 
					  void addMemberFile(Lazy *Body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  template <class ELFT> void init();
 | 
					  template <class ELFT> void init(uint16_t EMachine);
 | 
				
			||||||
  template <class ELFT> void resolve(SymbolBody *Body);
 | 
					  template <class ELFT> void resolve(SymbolBody *Body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
 | 
					  std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@
 | 
				
			||||||
#include "Config.h"
 | 
					#include "Config.h"
 | 
				
			||||||
#include "OutputSections.h"
 | 
					#include "OutputSections.h"
 | 
				
			||||||
#include "SymbolTable.h"
 | 
					#include "SymbolTable.h"
 | 
				
			||||||
 | 
					#include "Target.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "llvm/Support/FileOutputBuffer.h"
 | 
					#include "llvm/Support/FileOutputBuffer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,12 +257,12 @@ void Writer<ELFT>::scanRelocs(
 | 
				
			||||||
    if (!S)
 | 
					    if (!S)
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    uint32_t Type = RI.getType(IsMips64EL);
 | 
					    uint32_t Type = RI.getType(IsMips64EL);
 | 
				
			||||||
    if (relocNeedsPLT(Type)) {
 | 
					    if (Target->relocNeedsPlt(Type)) {
 | 
				
			||||||
      if (Body->isInPlt())
 | 
					      if (Body->isInPlt())
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      PltSec.addEntry(Body);
 | 
					      PltSec.addEntry(Body);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (relocNeedsGOT(Type)) {
 | 
					    if (Target->relocNeedsGot(Type)) {
 | 
				
			||||||
      if (Body->isInGot())
 | 
					      if (Body->isInGot())
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      GotSec.addEntry(Body);
 | 
					      GotSec.addEntry(Body);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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@PLT
 | 
				
			||||||
 | 
					  jmp bar@PLT
 | 
				
			||||||
 | 
					  jmp zed@PLT
 | 
				
			||||||
		Loading…
	
		Reference in New Issue