Refactor ELF type inference functions.

Previously, we initialized Config->EKind and Config->EMachine when
we instantiate ELF objects. That was not an ideal location to do that
because the logic was buried too deep inside a concrete logic.

This patch moves the code to the driver so that the initialization
becomes explicit.

Differential Revision: http://reviews.llvm.org/D21784

llvm-svn: 274089
This commit is contained in:
Rui Ueyama 2016-06-29 01:30:50 +00:00
parent 80a4702d02
commit 5e64d3fb94
5 changed files with 43 additions and 41 deletions

View File

@ -313,9 +313,6 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->Emulation = S;
}
if (Config->EMachine == EM_MIPS && Config->EKind == ELF64LEKind)
Config->Mips64EL = true;
Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
@ -470,6 +467,17 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
if (Files.empty() && !HasError)
error("no input files.");
// If -m <machine_type> was not given, infer it from object files.
if (Config->EKind == ELFNoneKind) {
for (std::unique_ptr<InputFile> &F : Files) {
if (F->EKind == ELFNoneKind)
continue;
Config->EKind = F->EKind;
Config->EMachine = F->EMachine;
break;
}
}
}
// Do actual linking. Note that when this function is called,
@ -484,6 +492,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
Script<ELFT>::X = &LS;
Config->Rela = ELFT::Is64Bits;
Config->Mips64EL =
(Config->EMachine == EM_MIPS && Config->EKind == ELF64LEKind);
// Add entry symbol. Note that AMDGPU binaries have no entry points.
if (Config->Entry.empty() && !Config->Shared && !Config->Relocatable &&

View File

@ -44,17 +44,19 @@ static ELFFile<ELFT> createELFObj(MemoryBufferRef MB) {
return F;
}
template <class ELFT>
ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB)
: InputFile(K, MB), ELFObj(createELFObj<ELFT>(MB)) {}
template <class ELFT>
ELFKind ELFFileBase<ELFT>::getELFKind() {
template <class ELFT> static ELFKind getELFKind() {
if (ELFT::TargetEndianness == support::little)
return ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind;
return ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind;
}
template <class ELFT>
ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB)
: InputFile(K, MB), ELFObj(createELFObj<ELFT>(MB)) {
EKind = getELFKind<ELFT>();
EMachine = ELFObj.getHeader()->e_machine;
}
template <class ELFT>
typename ELFT::SymRange ELFFileBase<ELFT>::getElfSymbols(bool OnlyGlobals) {
if (!Symtab)
@ -644,23 +646,6 @@ void BitcodeFile::parse(DenseSet<StringRef> &ComdatGroups) {
Symbols.push_back(createSymbol<ELFT>(KeptComdats, *Obj, Sym));
}
template <typename T>
static std::unique_ptr<InputFile> createELFFileAux(MemoryBufferRef MB) {
std::unique_ptr<T> Ret = llvm::make_unique<T>(MB);
if (!Config->FirstElf)
Config->FirstElf = Ret.get();
if (Config->EKind == ELFNoneKind) {
Config->EKind = Ret->getELFKind();
Config->EMachine = Ret->getEMachine();
if (Config->EMachine == EM_MIPS && Config->EKind == ELF64LEKind)
Config->Mips64EL = true;
}
return std::move(Ret);
}
template <template <class> class T>
static std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB) {
unsigned char Size;
@ -669,17 +654,21 @@ static std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB) {
if (Endian != ELFDATA2LSB && Endian != ELFDATA2MSB)
fatal("invalid data encoding: " + MB.getBufferIdentifier());
if (Size == ELFCLASS32) {
if (Endian == ELFDATA2LSB)
return createELFFileAux<T<ELF32LE>>(MB);
return createELFFileAux<T<ELF32BE>>(MB);
}
if (Size == ELFCLASS64) {
if (Endian == ELFDATA2LSB)
return createELFFileAux<T<ELF64LE>>(MB);
return createELFFileAux<T<ELF64BE>>(MB);
}
fatal("invalid file class: " + MB.getBufferIdentifier());
std::unique_ptr<InputFile> Obj;
if (Size == ELFCLASS32 && Endian == ELFDATA2LSB)
Obj.reset(new T<ELF32LE>(MB));
else if (Size == ELFCLASS32 && Endian == ELFDATA2MSB)
Obj.reset(new T<ELF32BE>(MB));
else if (Size == ELFCLASS64 && Endian == ELFDATA2LSB)
Obj.reset(new T<ELF64LE>(MB));
else if (Size == ELFCLASS64 && Endian == ELFDATA2MSB)
Obj.reset(new T<ELF64BE>(MB));
else
fatal("invalid file class: " + MB.getBufferIdentifier());
if (!Config->FirstElf)
Config->FirstElf = Obj.get();
return Obj;
}
static bool isBitcode(MemoryBufferRef MB) {

View File

@ -56,6 +56,11 @@ public:
// string for creating error messages.
StringRef ArchiveName;
// If this is an architecture-specific file, the following members
// have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
ELFKind EKind = ELFNoneKind;
uint16_t EMachine = llvm::ELF::EM_NONE;
protected:
InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
@ -79,11 +84,9 @@ public:
return K == ObjectKind || K == SharedKind;
}
static ELFKind getELFKind();
const llvm::object::ELFFile<ELFT> &getObj() const { return ELFObj; }
llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; }
uint16_t getEMachine() const { return getObj().getHeader()->e_machine; }
uint8_t getOSABI() const {
return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];
}

View File

@ -35,7 +35,7 @@ template <class ELFT> static bool isCompatible(InputFile *FileP) {
auto *F = dyn_cast<ELFFileBase<ELFT>>(FileP);
if (!F)
return true;
if (F->getELFKind() == Config->EKind && F->getEMachine() == Config->EMachine)
if (F->EKind == Config->EKind && F->EMachine == Config->EMachine)
return true;
StringRef A = F->getName();
StringRef B = Config->Emulation;

View File

@ -1304,7 +1304,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
EHdr->e_ident[EI_VERSION] = EV_CURRENT;
EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();
EHdr->e_type = getELFType();
EHdr->e_machine = FirstObj.getEMachine();
EHdr->e_machine = FirstObj.EMachine;
EHdr->e_version = EV_CURRENT;
EHdr->e_entry = getEntryAddr<ELFT>();
EHdr->e_shoff = SectionHeaderOff;