X86WinCOFFObjectWriter.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. //===-- X86WinCOFFObjectWriter.cpp - X86 Win COFF Writer ------------------===//
  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. #include "MCTargetDesc/X86FixupKinds.h"
  9. #include "MCTargetDesc/X86MCTargetDesc.h"
  10. #include "llvm/BinaryFormat/COFF.h"
  11. #include "llvm/MC/MCContext.h"
  12. #include "llvm/MC/MCExpr.h"
  13. #include "llvm/MC/MCFixup.h"
  14. #include "llvm/MC/MCObjectWriter.h"
  15. #include "llvm/MC/MCValue.h"
  16. #include "llvm/MC/MCWinCOFFObjectWriter.h"
  17. #include "llvm/Support/ErrorHandling.h"
  18. using namespace llvm;
  19. namespace {
  20. class X86WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
  21. public:
  22. X86WinCOFFObjectWriter(bool Is64Bit);
  23. ~X86WinCOFFObjectWriter() override = default;
  24. unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
  25. const MCFixup &Fixup, bool IsCrossSection,
  26. const MCAsmBackend &MAB) const override;
  27. };
  28. } // end anonymous namespace
  29. X86WinCOFFObjectWriter::X86WinCOFFObjectWriter(bool Is64Bit)
  30. : MCWinCOFFObjectTargetWriter(Is64Bit ? COFF::IMAGE_FILE_MACHINE_AMD64
  31. : COFF::IMAGE_FILE_MACHINE_I386) {}
  32. unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
  33. const MCValue &Target,
  34. const MCFixup &Fixup,
  35. bool IsCrossSection,
  36. const MCAsmBackend &MAB) const {
  37. const bool Is64Bit = getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64;
  38. unsigned FixupKind = Fixup.getKind();
  39. if (IsCrossSection) {
  40. // IMAGE_REL_AMD64_REL64 does not exist. We treat FK_Data_8 as FK_PCRel_4 so
  41. // that .quad a-b can lower to IMAGE_REL_AMD64_REL32. This allows generic
  42. // instrumentation to not bother with the COFF limitation. A negative value
  43. // needs attention.
  44. if (FixupKind == FK_Data_4 || FixupKind == llvm::X86::reloc_signed_4byte ||
  45. (FixupKind == FK_Data_8 && Is64Bit)) {
  46. FixupKind = FK_PCRel_4;
  47. } else {
  48. Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression");
  49. return COFF::IMAGE_REL_AMD64_ADDR32;
  50. }
  51. }
  52. MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
  53. MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
  54. if (Is64Bit) {
  55. switch (FixupKind) {
  56. case FK_PCRel_4:
  57. case X86::reloc_riprel_4byte:
  58. case X86::reloc_riprel_4byte_movq_load:
  59. case X86::reloc_riprel_4byte_relax:
  60. case X86::reloc_riprel_4byte_relax_rex:
  61. case X86::reloc_branch_4byte_pcrel:
  62. return COFF::IMAGE_REL_AMD64_REL32;
  63. case FK_Data_4:
  64. case X86::reloc_signed_4byte:
  65. case X86::reloc_signed_4byte_relax:
  66. if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
  67. return COFF::IMAGE_REL_AMD64_ADDR32NB;
  68. if (Modifier == MCSymbolRefExpr::VK_SECREL)
  69. return COFF::IMAGE_REL_AMD64_SECREL;
  70. return COFF::IMAGE_REL_AMD64_ADDR32;
  71. case FK_Data_8:
  72. return COFF::IMAGE_REL_AMD64_ADDR64;
  73. case FK_SecRel_2:
  74. return COFF::IMAGE_REL_AMD64_SECTION;
  75. case FK_SecRel_4:
  76. return COFF::IMAGE_REL_AMD64_SECREL;
  77. default:
  78. Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
  79. return COFF::IMAGE_REL_AMD64_ADDR32;
  80. }
  81. } else if (getMachine() == COFF::IMAGE_FILE_MACHINE_I386) {
  82. switch (FixupKind) {
  83. case FK_PCRel_4:
  84. case X86::reloc_riprel_4byte:
  85. case X86::reloc_riprel_4byte_movq_load:
  86. return COFF::IMAGE_REL_I386_REL32;
  87. case FK_Data_4:
  88. case X86::reloc_signed_4byte:
  89. case X86::reloc_signed_4byte_relax:
  90. if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
  91. return COFF::IMAGE_REL_I386_DIR32NB;
  92. if (Modifier == MCSymbolRefExpr::VK_SECREL)
  93. return COFF::IMAGE_REL_I386_SECREL;
  94. return COFF::IMAGE_REL_I386_DIR32;
  95. case FK_SecRel_2:
  96. return COFF::IMAGE_REL_I386_SECTION;
  97. case FK_SecRel_4:
  98. return COFF::IMAGE_REL_I386_SECREL;
  99. default:
  100. Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
  101. return COFF::IMAGE_REL_I386_DIR32;
  102. }
  103. } else
  104. llvm_unreachable("Unsupported COFF machine type.");
  105. }
  106. std::unique_ptr<MCObjectTargetWriter>
  107. llvm::createX86WinCOFFObjectWriter(bool Is64Bit) {
  108. return std::make_unique<X86WinCOFFObjectWriter>(Is64Bit);
  109. }