Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF.cpp
35271 views
//===-------------- COFF.cpp - JIT linker function for COFF -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// COFF jit-link function.9//10//===----------------------------------------------------------------------===//1112#include "llvm/ExecutionEngine/JITLink/COFF.h"1314#include "llvm/BinaryFormat/COFF.h"15#include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"16#include "llvm/Object/COFF.h"17#include "llvm/Support/Format.h"18#include "llvm/Support/MemoryBuffer.h"19#include <cstring>2021using namespace llvm;2223#define DEBUG_TYPE "jitlink"2425namespace llvm {26namespace jitlink {2728static StringRef getMachineName(uint16_t Machine) {29switch (Machine) {30case COFF::IMAGE_FILE_MACHINE_I386:31return "i386";32case COFF::IMAGE_FILE_MACHINE_AMD64:33return "x86_64";34case COFF::IMAGE_FILE_MACHINE_ARMNT:35return "ARM";36case COFF::IMAGE_FILE_MACHINE_ARM64:37return "ARM64";38default:39return "unknown";40}41}4243Expected<std::unique_ptr<LinkGraph>>44createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer) {45StringRef Data = ObjectBuffer.getBuffer();4647// Check magic48auto Magic = identify_magic(ObjectBuffer.getBuffer());49if (Magic != file_magic::coff_object)50return make_error<JITLinkError>("Invalid COFF buffer");5152if (Data.size() < sizeof(object::coff_file_header))53return make_error<JITLinkError>("Truncated COFF buffer");5455uint64_t CurPtr = 0;56bool IsPE = false;5758// Check if this is a PE/COFF file.59if (Data.size() >= sizeof(object::dos_header) + sizeof(COFF::PEMagic)) {60const auto *DH =61reinterpret_cast<const object::dos_header *>(Data.data() + CurPtr);62if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {63// Check the PE magic bytes. ("PE\0\0")64CurPtr = DH->AddressOfNewExeHeader;65if (memcmp(Data.data() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) !=660) {67return make_error<JITLinkError>("Incorrect PE magic");68}69CurPtr += sizeof(COFF::PEMagic);70IsPE = true;71}72}73if (Data.size() < CurPtr + sizeof(object::coff_file_header))74return make_error<JITLinkError>("Truncated COFF buffer");7576const object::coff_file_header *COFFHeader =77reinterpret_cast<const object::coff_file_header *>(Data.data() + CurPtr);78const object::coff_bigobj_file_header *COFFBigObjHeader = nullptr;7980// Deal with bigobj file81if (!IsPE && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&82COFFHeader->NumberOfSections == uint16_t(0xffff) &&83Data.size() >= sizeof(object::coff_bigobj_file_header)) {84if (Data.size() < sizeof(object::coff_file_header)) {85return make_error<JITLinkError>("Truncated COFF buffer");86}87COFFBigObjHeader =88reinterpret_cast<const object::coff_bigobj_file_header *>(Data.data() +89CurPtr);9091// Verify that we are dealing with bigobj.92if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&93std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,94sizeof(COFF::BigObjMagic)) == 0) {95COFFHeader = nullptr;96CurPtr += sizeof(object::coff_bigobj_file_header);97} else98COFFBigObjHeader = nullptr;99}100101uint16_t Machine =102COFFHeader ? COFFHeader->Machine : COFFBigObjHeader->Machine;103LLVM_DEBUG({104dbgs() << "jitLink_COFF: PE = " << (IsPE ? "yes" : "no")105<< ", bigobj = " << (COFFBigObjHeader ? "yes" : "no")106<< ", identifier = \"" << ObjectBuffer.getBufferIdentifier() << "\" "107<< "machine = " << getMachineName(Machine) << "\n";108});109110switch (Machine) {111case COFF::IMAGE_FILE_MACHINE_AMD64:112return createLinkGraphFromCOFFObject_x86_64(ObjectBuffer);113default:114return make_error<JITLinkError>(115"Unsupported target machine architecture in COFF object " +116ObjectBuffer.getBufferIdentifier() + ": " + getMachineName(Machine));117}118}119120void link_COFF(std::unique_ptr<LinkGraph> G,121std::unique_ptr<JITLinkContext> Ctx) {122switch (G->getTargetTriple().getArch()) {123case Triple::x86_64:124link_COFF_x86_64(std::move(G), std::move(Ctx));125return;126default:127Ctx->notifyFailed(make_error<JITLinkError>(128"Unsupported target machine architecture in COFF link graph " +129G->getName()));130return;131}132}133134} // end namespace jitlink135} // end namespace llvm136137138