diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -172,6 +172,7 @@ // generic class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder { private: + using ELFT = object::ELF64LE; static Expected getRelocationKind(const uint32_t Type) { @@ -206,149 +207,110 @@ } Error addRelocations() override { - LLVM_DEBUG(dbgs() << "Adding relocations\n"); - // TODO a partern is forming of iterate some sections but only give me - // ones I am interested, i should abstract that concept some where - for (auto &SecRef : Sections) { - if (SecRef.sh_type != ELF::SHT_RELA && SecRef.sh_type != ELF::SHT_REL) - continue; - // TODO can the elf obj file do this for me? - if (SecRef.sh_type == ELF::SHT_REL) - return make_error("Shouldn't have REL in x64", - llvm::inconvertibleErrorCode()); - - auto RelSectName = Obj.getSectionName(SecRef); - if (!RelSectName) - return RelSectName.takeError(); - - LLVM_DEBUG({ - dbgs() << "Adding relocations from section " << *RelSectName << "\n"; - }); - - auto UpdateSection = Obj.getSection(SecRef.sh_info); - if (!UpdateSection) - return UpdateSection.takeError(); - - auto UpdateSectionName = Obj.getSectionName(**UpdateSection); - if (!UpdateSectionName) - return UpdateSectionName.takeError(); - - // Don't process relocations for debug sections. - if (isDwarfSection(*UpdateSectionName)) { - LLVM_DEBUG({ - dbgs() << " Target is dwarf section " << *UpdateSectionName - << ". Skipping.\n"; - }); - continue; - } else - LLVM_DEBUG({ - dbgs() << " For target section " << *UpdateSectionName << "\n"; - }); - - auto JITSection = G->findSectionByName(*UpdateSectionName); - if (!JITSection) - return make_error( - "Refencing a a section that wasn't added to graph" + - *UpdateSectionName, - llvm::inconvertibleErrorCode()); - - auto Relocations = Obj.relas(SecRef); - if (!Relocations) - return Relocations.takeError(); - - for (const auto &Rela : *Relocations) { - auto Type = Rela.getType(false); - - LLVM_DEBUG({ - dbgs() << "Relocation Type: " << Type << "\n" - << "Name: " << Obj.getRelocationTypeName(Type) << "\n"; - }); - auto SymbolIndex = Rela.getSymbol(false); - auto Symbol = Obj.getRelocationSymbol(Rela, SymTabSec); - if (!Symbol) - return Symbol.takeError(); - - auto BlockToFix = *(JITSection->blocks().begin()); - auto *TargetSymbol = getGraphSymbol(SymbolIndex); - - if (!TargetSymbol) { - return make_error( - "Could not find symbol at given index, did you add it to " - "JITSymbolTable? index: " + - std::to_string(SymbolIndex) + - ", shndx: " + std::to_string((*Symbol)->st_shndx) + - " Size of table: " + std::to_string(GraphSymbols.size()), - llvm::inconvertibleErrorCode()); - } - int64_t Addend = Rela.r_addend; - JITTargetAddress FixupAddress = - (*UpdateSection)->sh_addr + Rela.r_offset; - - LLVM_DEBUG({ - dbgs() << "Processing relocation at " - << format("0x%016" PRIx64, FixupAddress) << "\n"; - }); - auto ELFRelocKind = getRelocationKind(Type); - if (!ELFRelocKind) - return ELFRelocKind.takeError(); - - Edge::Kind Kind = Edge::Invalid; - switch (*ELFRelocKind) { - case PCRel32: - Kind = x86_64::Delta32; - break; - case Delta64: - Kind = x86_64::Delta64; - break; - case Pointer32Signed: - Kind = x86_64::Pointer32Signed; - break; - case Pointer64: - Kind = x86_64::Pointer64; - break; - case PCRel32GOTLoad: { - Kind = x86_64::RequestGOTAndTransformToDelta32; - break; - } - case PCRel32REXGOTLoadRelaxable: { - Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable; - Addend = 0; - break; - } - case PCRel32GOTLoadRelaxable: { - Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable; - Addend = 0; - break; - } - case PCRel64GOT: { - Kind = x86_64::RequestGOTAndTransformToDelta64; - break; - } - case GOT64: { - Kind = x86_64::RequestGOTAndTransformToDelta64FromGOT; - break; - } - case GOTOFF64: { - Kind = x86_64::Delta64FromGOT; - break; - } - case Branch32: { - Kind = x86_64::BranchPCRel32; - Addend = 0; - break; - } - } + LLVM_DEBUG(dbgs() << "Processing relocations:\n"); + using Base = ELFLinkGraphBuilder; + + for (const auto &RelSect : Base::Sections) { + auto Process = [&](const auto &Rel, const auto &Target, Section &GS) { + // Sanity check the section we read relocation entries from. + if (RelSect.sh_type == ELF::SHT_REL) + return make_error( + "No SHT_REL in valid x64 ELF object files", + inconvertibleErrorCode()); + + return addSingleRelocation(Rel, Target, GS); + }; + + if (Error Err = Base::forEachRelocation(RelSect, std::move(Process))) + return Err; + } - LLVM_DEBUG({ - Edge GE(Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol, - Addend); - printEdge(dbgs(), *BlockToFix, GE, getELFX86RelocationKindName(Kind)); - dbgs() << "\n"; - }); - BlockToFix->addEdge(Kind, FixupAddress - BlockToFix->getAddress(), - *TargetSymbol, Addend); + return Error::success(); + } + + Error addSingleRelocation(const typename ELFT::Rela &Rel, + const typename ELFT::Shdr &FixupSection, + Section &GraphSection) { + using Base = ELFLinkGraphBuilder; + + uint32_t SymbolIndex = Rel.getSymbol(false); + auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); + if (!ObjSymbol) + return ObjSymbol.takeError(); + + Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); + if (!GraphSymbol) + return make_error( + formatv("Could not find symbol at given index, did you add it to " + "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", + SymbolIndex, (*ObjSymbol)->st_shndx, + Base::GraphSymbols.size()), + inconvertibleErrorCode()); + + // Sanity check the relocation kind. + auto ELFRelocKind = getRelocationKind(Rel.getType(false)); + if (!ELFRelocKind) + return ELFRelocKind.takeError(); + + int64_t Addend = Rel.r_addend; + Edge::Kind Kind = Edge::Invalid; + switch (*ELFRelocKind) { + case PCRel32: + Kind = x86_64::Delta32; + break; + case Delta64: + Kind = x86_64::Delta64; + break; + case Pointer32Signed: + Kind = x86_64::Pointer32Signed; + break; + case Pointer64: + Kind = x86_64::Pointer64; + break; + case PCRel32GOTLoad: { + Kind = x86_64::RequestGOTAndTransformToDelta32; + break; + } + case PCRel32REXGOTLoadRelaxable: { + Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable; + Addend = 0; + break; + } + case PCRel32GOTLoadRelaxable: { + Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable; + Addend = 0; + break; + } + case PCRel64GOT: { + Kind = x86_64::RequestGOTAndTransformToDelta64; + break; + } + case GOT64: { + Kind = x86_64::RequestGOTAndTransformToDelta64FromGOT; + break; + } + case GOTOFF64: { + Kind = x86_64::Delta64FromGOT; + break; + } + case Branch32: { + Kind = x86_64::BranchPCRel32; + Addend = 0; + break; } } + + Block *BlockToFix = *(GraphSection.blocks().begin()); + JITTargetAddress FixupAddress = FixupSection.sh_addr + Rel.r_offset; + Edge::OffsetT Offset = FixupAddress - BlockToFix->getAddress(); + Edge GE(Kind, Offset, *GraphSymbol, Addend); + LLVM_DEBUG({ + dbgs() << " "; + printEdge(dbgs(), *BlockToFix, GE, getELFX86RelocationKindName(Kind)); + dbgs() << "\n"; + }); + + BlockToFix->addEdge(std::move(GE)); return Error::success(); }