brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.5 KiB · d370e99 Raw
136 lines · cpp
1//===-------------- COFF.cpp - JIT linker function for COFF -------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// COFF jit-link function.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ExecutionEngine/JITLink/COFF.h"14 15#include "llvm/BinaryFormat/COFF.h"16#include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"17#include "llvm/Object/COFF.h"18#include <cstring>19 20using namespace llvm;21 22#define DEBUG_TYPE "jitlink"23 24namespace llvm {25namespace jitlink {26 27static StringRef getMachineName(uint16_t Machine) {28  switch (Machine) {29  case COFF::IMAGE_FILE_MACHINE_I386:30    return "i386";31  case COFF::IMAGE_FILE_MACHINE_AMD64:32    return "x86_64";33  case COFF::IMAGE_FILE_MACHINE_ARMNT:34    return "ARM";35  case COFF::IMAGE_FILE_MACHINE_ARM64:36    return "ARM64";37  default:38    return "unknown";39  }40}41 42Expected<std::unique_ptr<LinkGraph>>43createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer,44                              std::shared_ptr<orc::SymbolStringPool> SSP) {45  StringRef Data = ObjectBuffer.getBuffer();46 47  // Check magic48  auto Magic = identify_magic(ObjectBuffer.getBuffer());49  if (Magic != file_magic::coff_object)50    return make_error<JITLinkError>("Invalid COFF buffer");51 52  if (Data.size() < sizeof(object::coff_file_header))53    return make_error<JITLinkError>("Truncated COFF buffer");54 55  uint64_t CurPtr = 0;56  bool IsPE = false;57 58  // Check if this is a PE/COFF file.59  if (Data.size() >= sizeof(object::dos_header) + sizeof(COFF::PEMagic)) {60    const auto *DH =61        reinterpret_cast<const object::dos_header *>(Data.data() + CurPtr);62    if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {63      // Check the PE magic bytes. ("PE\0\0")64      CurPtr = DH->AddressOfNewExeHeader;65      if (memcmp(Data.data() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) !=66          0) {67        return make_error<JITLinkError>("Incorrect PE magic");68      }69      CurPtr += sizeof(COFF::PEMagic);70      IsPE = true;71    }72  }73  if (Data.size() < CurPtr + sizeof(object::coff_file_header))74    return make_error<JITLinkError>("Truncated COFF buffer");75 76  const object::coff_file_header *COFFHeader =77      reinterpret_cast<const object::coff_file_header *>(Data.data() + CurPtr);78  const object::coff_bigobj_file_header *COFFBigObjHeader = nullptr;79 80  // Deal with bigobj file81  if (!IsPE && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&82      COFFHeader->NumberOfSections == uint16_t(0xffff) &&83      Data.size() >= sizeof(object::coff_bigobj_file_header)) {84    if (Data.size() < sizeof(object::coff_file_header)) {85      return make_error<JITLinkError>("Truncated COFF buffer");86    }87    COFFBigObjHeader =88        reinterpret_cast<const object::coff_bigobj_file_header *>(Data.data() +89                                                                  CurPtr);90 91    // Verify that we are dealing with bigobj.92    if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&93        std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,94                    sizeof(COFF::BigObjMagic)) == 0) {95      COFFHeader = nullptr;96      CurPtr += sizeof(object::coff_bigobj_file_header);97    } else98      COFFBigObjHeader = nullptr;99  }100 101  uint16_t Machine =102      COFFHeader ? COFFHeader->Machine : COFFBigObjHeader->Machine;103  LLVM_DEBUG({104    dbgs() << "jitLink_COFF: PE = " << (IsPE ? "yes" : "no")105           << ", bigobj = " << (COFFBigObjHeader ? "yes" : "no")106           << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() << "\" "107           << "machine = " << getMachineName(Machine) << "\n";108  });109 110  switch (Machine) {111  case COFF::IMAGE_FILE_MACHINE_AMD64:112    return createLinkGraphFromCOFFObject_x86_64(ObjectBuffer, std::move(SSP));113  default:114    return make_error<JITLinkError>(115        "Unsupported target machine architecture in COFF object " +116        ObjectBuffer.getBufferIdentifier() + ": " + getMachineName(Machine));117  }118}119 120void link_COFF(std::unique_ptr<LinkGraph> G,121               std::unique_ptr<JITLinkContext> Ctx) {122  switch (G->getTargetTriple().getArch()) {123  case Triple::x86_64:124    link_COFF_x86_64(std::move(G), std::move(Ctx));125    return;126  default:127    Ctx->notifyFailed(make_error<JITLinkError>(128        "Unsupported target machine architecture in COFF link graph " +129        G->getName()));130    return;131  }132}133 134} // end namespace jitlink135} // end namespace llvm136