X86ELFObjectWriter.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. //===-- X86ELFObjectWriter.cpp - X86 ELF 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/ELF.h"
  11. #include "llvm/MC/MCAsmInfo.h"
  12. #include "llvm/MC/MCContext.h"
  13. #include "llvm/MC/MCELFObjectWriter.h"
  14. #include "llvm/MC/MCExpr.h"
  15. #include "llvm/MC/MCFixup.h"
  16. #include "llvm/MC/MCObjectWriter.h"
  17. #include "llvm/MC/MCValue.h"
  18. #include "llvm/Support/ErrorHandling.h"
  19. #include <cassert>
  20. #include <cstdint>
  21. using namespace llvm;
  22. namespace {
  23. class X86ELFObjectWriter : public MCELFObjectTargetWriter {
  24. public:
  25. X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
  26. ~X86ELFObjectWriter() override = default;
  27. protected:
  28. unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
  29. const MCFixup &Fixup, bool IsPCRel) const override;
  30. };
  31. } // end anonymous namespace
  32. X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
  33. uint16_t EMachine)
  34. : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
  35. // Only i386 and IAMCU use Rel instead of RelA.
  36. /*HasRelocationAddend*/
  37. (EMachine != ELF::EM_386) &&
  38. (EMachine != ELF::EM_IAMCU)) {}
  39. enum X86_64RelType { RT64_NONE, RT64_64, RT64_32, RT64_32S, RT64_16, RT64_8 };
  40. static X86_64RelType getType64(MCFixupKind Kind,
  41. MCSymbolRefExpr::VariantKind &Modifier,
  42. bool &IsPCRel) {
  43. switch (unsigned(Kind)) {
  44. default:
  45. llvm_unreachable("Unimplemented");
  46. case FK_NONE:
  47. return RT64_NONE;
  48. case X86::reloc_global_offset_table8:
  49. Modifier = MCSymbolRefExpr::VK_GOT;
  50. IsPCRel = true;
  51. return RT64_64;
  52. case FK_Data_8:
  53. return RT64_64;
  54. case X86::reloc_signed_4byte:
  55. case X86::reloc_signed_4byte_relax:
  56. if (Modifier == MCSymbolRefExpr::VK_None && !IsPCRel)
  57. return RT64_32S;
  58. return RT64_32;
  59. case X86::reloc_global_offset_table:
  60. Modifier = MCSymbolRefExpr::VK_GOT;
  61. IsPCRel = true;
  62. return RT64_32;
  63. case FK_Data_4:
  64. case FK_PCRel_4:
  65. case X86::reloc_riprel_4byte:
  66. case X86::reloc_riprel_4byte_relax:
  67. case X86::reloc_riprel_4byte_relax_rex:
  68. case X86::reloc_riprel_4byte_movq_load:
  69. return RT64_32;
  70. case X86::reloc_branch_4byte_pcrel:
  71. Modifier = MCSymbolRefExpr::VK_PLT;
  72. return RT64_32;
  73. case FK_PCRel_2:
  74. case FK_Data_2:
  75. return RT64_16;
  76. case FK_PCRel_1:
  77. case FK_Data_1:
  78. return RT64_8;
  79. }
  80. }
  81. static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) {
  82. if (Type != RT64_32)
  83. Ctx.reportError(Loc,
  84. "32 bit reloc applied to a field with a different size");
  85. }
  86. static void checkIs64(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) {
  87. if (Type != RT64_64)
  88. Ctx.reportError(Loc,
  89. "64 bit reloc applied to a field with a different size");
  90. }
  91. static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
  92. MCSymbolRefExpr::VariantKind Modifier,
  93. X86_64RelType Type, bool IsPCRel,
  94. MCFixupKind Kind) {
  95. switch (Modifier) {
  96. default:
  97. llvm_unreachable("Unimplemented");
  98. case MCSymbolRefExpr::VK_None:
  99. case MCSymbolRefExpr::VK_X86_ABS8:
  100. switch (Type) {
  101. case RT64_NONE:
  102. if (Modifier == MCSymbolRefExpr::VK_None)
  103. return ELF::R_X86_64_NONE;
  104. llvm_unreachable("Unimplemented");
  105. case RT64_64:
  106. return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64;
  107. case RT64_32:
  108. return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32;
  109. case RT64_32S:
  110. return ELF::R_X86_64_32S;
  111. case RT64_16:
  112. return IsPCRel ? ELF::R_X86_64_PC16 : ELF::R_X86_64_16;
  113. case RT64_8:
  114. return IsPCRel ? ELF::R_X86_64_PC8 : ELF::R_X86_64_8;
  115. }
  116. llvm_unreachable("unexpected relocation type!");
  117. case MCSymbolRefExpr::VK_GOT:
  118. switch (Type) {
  119. case RT64_64:
  120. return IsPCRel ? ELF::R_X86_64_GOTPC64 : ELF::R_X86_64_GOT64;
  121. case RT64_32:
  122. return IsPCRel ? ELF::R_X86_64_GOTPC32 : ELF::R_X86_64_GOT32;
  123. case RT64_32S:
  124. case RT64_16:
  125. case RT64_8:
  126. case RT64_NONE:
  127. llvm_unreachable("Unimplemented");
  128. }
  129. llvm_unreachable("unexpected relocation type!");
  130. case MCSymbolRefExpr::VK_GOTOFF:
  131. assert(Type == RT64_64);
  132. assert(!IsPCRel);
  133. return ELF::R_X86_64_GOTOFF64;
  134. case MCSymbolRefExpr::VK_TPOFF:
  135. assert(!IsPCRel);
  136. switch (Type) {
  137. case RT64_64:
  138. return ELF::R_X86_64_TPOFF64;
  139. case RT64_32:
  140. return ELF::R_X86_64_TPOFF32;
  141. case RT64_32S:
  142. case RT64_16:
  143. case RT64_8:
  144. case RT64_NONE:
  145. llvm_unreachable("Unimplemented");
  146. }
  147. llvm_unreachable("unexpected relocation type!");
  148. case MCSymbolRefExpr::VK_DTPOFF:
  149. assert(!IsPCRel);
  150. switch (Type) {
  151. case RT64_64:
  152. return ELF::R_X86_64_DTPOFF64;
  153. case RT64_32:
  154. return ELF::R_X86_64_DTPOFF32;
  155. case RT64_32S:
  156. case RT64_16:
  157. case RT64_8:
  158. case RT64_NONE:
  159. llvm_unreachable("Unimplemented");
  160. }
  161. llvm_unreachable("unexpected relocation type!");
  162. case MCSymbolRefExpr::VK_SIZE:
  163. assert(!IsPCRel);
  164. switch (Type) {
  165. case RT64_64:
  166. return ELF::R_X86_64_SIZE64;
  167. case RT64_32:
  168. return ELF::R_X86_64_SIZE32;
  169. case RT64_32S:
  170. case RT64_16:
  171. case RT64_8:
  172. case RT64_NONE:
  173. llvm_unreachable("Unimplemented");
  174. }
  175. llvm_unreachable("unexpected relocation type!");
  176. case MCSymbolRefExpr::VK_TLSCALL:
  177. return ELF::R_X86_64_TLSDESC_CALL;
  178. case MCSymbolRefExpr::VK_TLSDESC:
  179. return ELF::R_X86_64_GOTPC32_TLSDESC;
  180. case MCSymbolRefExpr::VK_TLSGD:
  181. checkIs32(Ctx, Loc, Type);
  182. return ELF::R_X86_64_TLSGD;
  183. case MCSymbolRefExpr::VK_GOTTPOFF:
  184. checkIs32(Ctx, Loc, Type);
  185. return ELF::R_X86_64_GOTTPOFF;
  186. case MCSymbolRefExpr::VK_TLSLD:
  187. checkIs32(Ctx, Loc, Type);
  188. return ELF::R_X86_64_TLSLD;
  189. case MCSymbolRefExpr::VK_PLT:
  190. checkIs32(Ctx, Loc, Type);
  191. return ELF::R_X86_64_PLT32;
  192. case MCSymbolRefExpr::VK_GOTPCREL:
  193. checkIs32(Ctx, Loc, Type);
  194. // Older versions of ld.bfd/ld.gold/lld
  195. // do not support GOTPCRELX/REX_GOTPCRELX,
  196. // and we want to keep back-compatibility.
  197. if (!Ctx.getAsmInfo()->canRelaxRelocations())
  198. return ELF::R_X86_64_GOTPCREL;
  199. switch (unsigned(Kind)) {
  200. default:
  201. return ELF::R_X86_64_GOTPCREL;
  202. case X86::reloc_riprel_4byte_relax:
  203. return ELF::R_X86_64_GOTPCRELX;
  204. case X86::reloc_riprel_4byte_relax_rex:
  205. case X86::reloc_riprel_4byte_movq_load:
  206. return ELF::R_X86_64_REX_GOTPCRELX;
  207. }
  208. llvm_unreachable("unexpected relocation type!");
  209. case MCSymbolRefExpr::VK_GOTPCREL_NORELAX:
  210. checkIs32(Ctx, Loc, Type);
  211. return ELF::R_X86_64_GOTPCREL;
  212. case MCSymbolRefExpr::VK_X86_PLTOFF:
  213. checkIs64(Ctx, Loc, Type);
  214. return ELF::R_X86_64_PLTOFF64;
  215. }
  216. }
  217. enum X86_32RelType { RT32_NONE, RT32_32, RT32_16, RT32_8 };
  218. static X86_32RelType getType32(X86_64RelType T) {
  219. switch (T) {
  220. case RT64_NONE:
  221. return RT32_NONE;
  222. case RT64_64:
  223. llvm_unreachable("Unimplemented");
  224. case RT64_32:
  225. case RT64_32S:
  226. return RT32_32;
  227. case RT64_16:
  228. return RT32_16;
  229. case RT64_8:
  230. return RT32_8;
  231. }
  232. llvm_unreachable("unexpected relocation type!");
  233. }
  234. static unsigned getRelocType32(MCContext &Ctx,
  235. MCSymbolRefExpr::VariantKind Modifier,
  236. X86_32RelType Type, bool IsPCRel,
  237. MCFixupKind Kind) {
  238. switch (Modifier) {
  239. default:
  240. llvm_unreachable("Unimplemented");
  241. case MCSymbolRefExpr::VK_None:
  242. case MCSymbolRefExpr::VK_X86_ABS8:
  243. switch (Type) {
  244. case RT32_NONE:
  245. if (Modifier == MCSymbolRefExpr::VK_None)
  246. return ELF::R_386_NONE;
  247. llvm_unreachable("Unimplemented");
  248. case RT32_32:
  249. return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32;
  250. case RT32_16:
  251. return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16;
  252. case RT32_8:
  253. return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8;
  254. }
  255. llvm_unreachable("unexpected relocation type!");
  256. case MCSymbolRefExpr::VK_GOT:
  257. assert(Type == RT32_32);
  258. if (IsPCRel)
  259. return ELF::R_386_GOTPC;
  260. // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we
  261. // want to maintain compatibility.
  262. if (!Ctx.getAsmInfo()->canRelaxRelocations())
  263. return ELF::R_386_GOT32;
  264. return Kind == MCFixupKind(X86::reloc_signed_4byte_relax)
  265. ? ELF::R_386_GOT32X
  266. : ELF::R_386_GOT32;
  267. case MCSymbolRefExpr::VK_GOTOFF:
  268. assert(Type == RT32_32);
  269. assert(!IsPCRel);
  270. return ELF::R_386_GOTOFF;
  271. case MCSymbolRefExpr::VK_TLSCALL:
  272. return ELF::R_386_TLS_DESC_CALL;
  273. case MCSymbolRefExpr::VK_TLSDESC:
  274. return ELF::R_386_TLS_GOTDESC;
  275. case MCSymbolRefExpr::VK_TPOFF:
  276. assert(Type == RT32_32);
  277. assert(!IsPCRel);
  278. return ELF::R_386_TLS_LE_32;
  279. case MCSymbolRefExpr::VK_DTPOFF:
  280. assert(Type == RT32_32);
  281. assert(!IsPCRel);
  282. return ELF::R_386_TLS_LDO_32;
  283. case MCSymbolRefExpr::VK_TLSGD:
  284. assert(Type == RT32_32);
  285. assert(!IsPCRel);
  286. return ELF::R_386_TLS_GD;
  287. case MCSymbolRefExpr::VK_GOTTPOFF:
  288. assert(Type == RT32_32);
  289. assert(!IsPCRel);
  290. return ELF::R_386_TLS_IE_32;
  291. case MCSymbolRefExpr::VK_PLT:
  292. assert(Type == RT32_32);
  293. return ELF::R_386_PLT32;
  294. case MCSymbolRefExpr::VK_INDNTPOFF:
  295. assert(Type == RT32_32);
  296. assert(!IsPCRel);
  297. return ELF::R_386_TLS_IE;
  298. case MCSymbolRefExpr::VK_NTPOFF:
  299. assert(Type == RT32_32);
  300. assert(!IsPCRel);
  301. return ELF::R_386_TLS_LE;
  302. case MCSymbolRefExpr::VK_GOTNTPOFF:
  303. assert(Type == RT32_32);
  304. assert(!IsPCRel);
  305. return ELF::R_386_TLS_GOTIE;
  306. case MCSymbolRefExpr::VK_TLSLDM:
  307. assert(Type == RT32_32);
  308. assert(!IsPCRel);
  309. return ELF::R_386_TLS_LDM;
  310. }
  311. }
  312. unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
  313. const MCFixup &Fixup,
  314. bool IsPCRel) const {
  315. MCFixupKind Kind = Fixup.getKind();
  316. if (Kind >= FirstLiteralRelocationKind)
  317. return Kind - FirstLiteralRelocationKind;
  318. MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
  319. X86_64RelType Type = getType64(Kind, Modifier, IsPCRel);
  320. if (getEMachine() == ELF::EM_X86_64)
  321. return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind);
  322. assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
  323. "Unsupported ELF machine type.");
  324. return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind);
  325. }
  326. std::unique_ptr<MCObjectTargetWriter>
  327. llvm::createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine) {
  328. return std::make_unique<X86ELFObjectWriter>(IsELF64, OSABI, EMachine);
  329. }