COFF.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // COFF jit-link function.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/ExecutionEngine/JITLink/COFF.h"
  13. #include "llvm/BinaryFormat/COFF.h"
  14. #include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"
  15. #include "llvm/Object/COFF.h"
  16. #include "llvm/Support/Endian.h"
  17. #include "llvm/Support/Format.h"
  18. #include "llvm/Support/MemoryBuffer.h"
  19. #include <cstring>
  20. using namespace llvm;
  21. #define DEBUG_TYPE "jitlink"
  22. namespace llvm {
  23. namespace jitlink {
  24. static StringRef getMachineName(uint16_t Machine) {
  25. switch (Machine) {
  26. case COFF::IMAGE_FILE_MACHINE_I386:
  27. return "i386";
  28. case COFF::IMAGE_FILE_MACHINE_AMD64:
  29. return "x86_64";
  30. case COFF::IMAGE_FILE_MACHINE_ARMNT:
  31. return "ARM";
  32. case COFF::IMAGE_FILE_MACHINE_ARM64:
  33. return "ARM64";
  34. default:
  35. return "unknown";
  36. }
  37. }
  38. Expected<std::unique_ptr<LinkGraph>>
  39. createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer) {
  40. StringRef Data = ObjectBuffer.getBuffer();
  41. // Check magic
  42. auto Magic = identify_magic(ObjectBuffer.getBuffer());
  43. if (Magic != file_magic::coff_object)
  44. return make_error<JITLinkError>("Invalid COFF buffer");
  45. if (Data.size() < sizeof(object::coff_file_header))
  46. return make_error<JITLinkError>("Truncated COFF buffer");
  47. uint64_t CurPtr = 0;
  48. bool IsPE = false;
  49. // Check if this is a PE/COFF file.
  50. if (Data.size() >= sizeof(object::dos_header) + sizeof(COFF::PEMagic)) {
  51. const auto *DH =
  52. reinterpret_cast<const object::dos_header *>(Data.data() + CurPtr);
  53. if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
  54. // Check the PE magic bytes. ("PE\0\0")
  55. CurPtr = DH->AddressOfNewExeHeader;
  56. if (memcmp(Data.data() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) !=
  57. 0) {
  58. return make_error<JITLinkError>("Incorrect PE magic");
  59. }
  60. CurPtr += sizeof(COFF::PEMagic);
  61. IsPE = true;
  62. }
  63. }
  64. if (Data.size() < CurPtr + sizeof(object::coff_file_header))
  65. return make_error<JITLinkError>("Truncated COFF buffer");
  66. const object::coff_file_header *COFFHeader =
  67. reinterpret_cast<const object::coff_file_header *>(Data.data() + CurPtr);
  68. const object::coff_bigobj_file_header *COFFBigObjHeader = nullptr;
  69. // Deal with bigobj file
  70. if (!IsPE && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
  71. COFFHeader->NumberOfSections == uint16_t(0xffff) &&
  72. Data.size() >= sizeof(object::coff_bigobj_file_header)) {
  73. if (Data.size() < sizeof(object::coff_file_header)) {
  74. return make_error<JITLinkError>("Truncated COFF buffer");
  75. }
  76. COFFBigObjHeader =
  77. reinterpret_cast<const object::coff_bigobj_file_header *>(Data.data() +
  78. CurPtr);
  79. // Verify that we are dealing with bigobj.
  80. if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
  81. std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
  82. sizeof(COFF::BigObjMagic)) == 0) {
  83. COFFHeader = nullptr;
  84. CurPtr += sizeof(object::coff_bigobj_file_header);
  85. } else
  86. COFFBigObjHeader = nullptr;
  87. }
  88. uint16_t Machine =
  89. COFFHeader ? COFFHeader->Machine : COFFBigObjHeader->Machine;
  90. LLVM_DEBUG({
  91. dbgs() << "jitLink_COFF: PE = " << (IsPE ? "yes" : "no")
  92. << ", bigobj = " << (COFFBigObjHeader ? "yes" : "no")
  93. << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() << "\" "
  94. << "machine = " << getMachineName(Machine) << "\n";
  95. });
  96. switch (Machine) {
  97. case COFF::IMAGE_FILE_MACHINE_AMD64:
  98. return createLinkGraphFromCOFFObject_x86_64(ObjectBuffer);
  99. default:
  100. return make_error<JITLinkError>(
  101. "Unsupported target machine architecture in COFF object " +
  102. ObjectBuffer.getBufferIdentifier() + ": " + getMachineName(Machine));
  103. }
  104. }
  105. void link_COFF(std::unique_ptr<LinkGraph> G,
  106. std::unique_ptr<JITLinkContext> Ctx) {
  107. switch (G->getTargetTriple().getArch()) {
  108. case Triple::x86_64:
  109. link_COFF_x86_64(std::move(G), std::move(Ctx));
  110. return;
  111. default:
  112. Ctx->notifyFailed(make_error<JITLinkError>(
  113. "Unsupported target machine architecture in COFF link graph " +
  114. G->getName()));
  115. return;
  116. }
  117. }
  118. } // end namespace jitlink
  119. } // end namespace llvm