ARMELFObjectWriter.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. //===-- ARMELFObjectWriter.cpp - ARM 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/ARMFixupKinds.h"
  9. #include "MCTargetDesc/ARMMCTargetDesc.h"
  10. #include "llvm/BinaryFormat/ELF.h"
  11. #include "llvm/MC/MCContext.h"
  12. #include "llvm/MC/MCELFObjectWriter.h"
  13. #include "llvm/MC/MCExpr.h"
  14. #include "llvm/MC/MCFixup.h"
  15. #include "llvm/MC/MCObjectFileInfo.h"
  16. #include "llvm/MC/MCObjectWriter.h"
  17. #include "llvm/MC/MCValue.h"
  18. #include "llvm/Support/ErrorHandling.h"
  19. #include "llvm/Support/raw_ostream.h"
  20. #include <cstdint>
  21. using namespace llvm;
  22. namespace {
  23. class ARMELFObjectWriter : public MCELFObjectTargetWriter {
  24. enum { DefaultEABIVersion = 0x05000000U };
  25. unsigned GetRelocTypeInner(const MCValue &Target, const MCFixup &Fixup,
  26. bool IsPCRel, MCContext &Ctx) const;
  27. public:
  28. ARMELFObjectWriter(uint8_t OSABI);
  29. ~ARMELFObjectWriter() override = default;
  30. unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
  31. const MCFixup &Fixup, bool IsPCRel) const override;
  32. bool needsRelocateWithSymbol(const MCSymbol &Sym,
  33. unsigned Type) const override;
  34. void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec) override;
  35. };
  36. } // end anonymous namespace
  37. ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
  38. : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
  39. ELF::EM_ARM,
  40. /*HasRelocationAddend*/ false) {}
  41. bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
  42. unsigned Type) const {
  43. // FIXME: This is extremely conservative. This really needs to use an
  44. // explicit list with a clear explanation for why each realocation needs to
  45. // point to the symbol, not to the section.
  46. switch (Type) {
  47. default:
  48. return true;
  49. case ELF::R_ARM_PREL31:
  50. case ELF::R_ARM_ABS32:
  51. return false;
  52. }
  53. }
  54. // Need to examine the Fixup when determining whether to
  55. // emit the relocation as an explicit symbol or as a section relative
  56. // offset
  57. unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
  58. const MCFixup &Fixup,
  59. bool IsPCRel) const {
  60. return GetRelocTypeInner(Target, Fixup, IsPCRel, Ctx);
  61. }
  62. unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
  63. const MCFixup &Fixup,
  64. bool IsPCRel,
  65. MCContext &Ctx) const {
  66. unsigned Kind = Fixup.getTargetKind();
  67. if (Kind >= FirstLiteralRelocationKind)
  68. return Kind - FirstLiteralRelocationKind;
  69. MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
  70. if (IsPCRel) {
  71. switch (Fixup.getTargetKind()) {
  72. default:
  73. Ctx.reportError(Fixup.getLoc(), "unsupported relocation on symbol");
  74. return ELF::R_ARM_NONE;
  75. case FK_Data_4:
  76. switch (Modifier) {
  77. default:
  78. Ctx.reportError(Fixup.getLoc(),
  79. "invalid fixup for 4-byte pc-relative data relocation");
  80. return ELF::R_ARM_NONE;
  81. case MCSymbolRefExpr::VK_None: {
  82. if (const MCSymbolRefExpr *SymRef = Target.getSymA()) {
  83. // For GNU AS compatibility expressions such as
  84. // _GLOBAL_OFFSET_TABLE_ - label emit a R_ARM_BASE_PREL relocation.
  85. if (SymRef->getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_")
  86. return ELF::R_ARM_BASE_PREL;
  87. }
  88. return ELF::R_ARM_REL32;
  89. }
  90. case MCSymbolRefExpr::VK_GOTTPOFF:
  91. return ELF::R_ARM_TLS_IE32;
  92. case MCSymbolRefExpr::VK_ARM_GOT_PREL:
  93. return ELF::R_ARM_GOT_PREL;
  94. case MCSymbolRefExpr::VK_ARM_PREL31:
  95. return ELF::R_ARM_PREL31;
  96. }
  97. case ARM::fixup_arm_blx:
  98. case ARM::fixup_arm_uncondbl:
  99. switch (Modifier) {
  100. case MCSymbolRefExpr::VK_PLT:
  101. return ELF::R_ARM_CALL;
  102. case MCSymbolRefExpr::VK_TLSCALL:
  103. return ELF::R_ARM_TLS_CALL;
  104. default:
  105. return ELF::R_ARM_CALL;
  106. }
  107. case ARM::fixup_arm_condbl:
  108. case ARM::fixup_arm_condbranch:
  109. case ARM::fixup_arm_uncondbranch:
  110. return ELF::R_ARM_JUMP24;
  111. case ARM::fixup_t2_condbranch:
  112. return ELF::R_ARM_THM_JUMP19;
  113. case ARM::fixup_t2_uncondbranch:
  114. return ELF::R_ARM_THM_JUMP24;
  115. case ARM::fixup_arm_movt_hi16:
  116. return ELF::R_ARM_MOVT_PREL;
  117. case ARM::fixup_arm_movw_lo16:
  118. return ELF::R_ARM_MOVW_PREL_NC;
  119. case ARM::fixup_t2_movt_hi16:
  120. return ELF::R_ARM_THM_MOVT_PREL;
  121. case ARM::fixup_t2_movw_lo16:
  122. return ELF::R_ARM_THM_MOVW_PREL_NC;
  123. case ARM::fixup_arm_thumb_br:
  124. return ELF::R_ARM_THM_JUMP11;
  125. case ARM::fixup_arm_thumb_bcc:
  126. return ELF::R_ARM_THM_JUMP8;
  127. case ARM::fixup_arm_thumb_bl:
  128. case ARM::fixup_arm_thumb_blx:
  129. switch (Modifier) {
  130. case MCSymbolRefExpr::VK_TLSCALL:
  131. return ELF::R_ARM_THM_TLS_CALL;
  132. default:
  133. return ELF::R_ARM_THM_CALL;
  134. }
  135. case ARM::fixup_bf_target:
  136. return ELF::R_ARM_THM_BF16;
  137. case ARM::fixup_bfc_target:
  138. return ELF::R_ARM_THM_BF12;
  139. case ARM::fixup_bfl_target:
  140. return ELF::R_ARM_THM_BF18;
  141. }
  142. }
  143. switch (Kind) {
  144. default:
  145. Ctx.reportError(Fixup.getLoc(), "unsupported relocation on symbol");
  146. return ELF::R_ARM_NONE;
  147. case FK_Data_1:
  148. switch (Modifier) {
  149. default:
  150. Ctx.reportError(Fixup.getLoc(),
  151. "invalid fixup for 1-byte data relocation");
  152. return ELF::R_ARM_NONE;
  153. case MCSymbolRefExpr::VK_None:
  154. return ELF::R_ARM_ABS8;
  155. }
  156. case FK_Data_2:
  157. switch (Modifier) {
  158. default:
  159. Ctx.reportError(Fixup.getLoc(),
  160. "invalid fixup for 2-byte data relocation");
  161. return ELF::R_ARM_NONE;
  162. case MCSymbolRefExpr::VK_None:
  163. return ELF::R_ARM_ABS16;
  164. }
  165. case FK_Data_4:
  166. switch (Modifier) {
  167. default:
  168. Ctx.reportError(Fixup.getLoc(),
  169. "invalid fixup for 4-byte data relocation");
  170. return ELF::R_ARM_NONE;
  171. case MCSymbolRefExpr::VK_ARM_NONE:
  172. return ELF::R_ARM_NONE;
  173. case MCSymbolRefExpr::VK_GOT:
  174. return ELF::R_ARM_GOT_BREL;
  175. case MCSymbolRefExpr::VK_TLSGD:
  176. return ELF::R_ARM_TLS_GD32;
  177. case MCSymbolRefExpr::VK_TPOFF:
  178. return ELF::R_ARM_TLS_LE32;
  179. case MCSymbolRefExpr::VK_GOTTPOFF:
  180. return ELF::R_ARM_TLS_IE32;
  181. case MCSymbolRefExpr::VK_None:
  182. return ELF::R_ARM_ABS32;
  183. case MCSymbolRefExpr::VK_GOTOFF:
  184. return ELF::R_ARM_GOTOFF32;
  185. case MCSymbolRefExpr::VK_ARM_GOT_PREL:
  186. return ELF::R_ARM_GOT_PREL;
  187. case MCSymbolRefExpr::VK_ARM_TARGET1:
  188. return ELF::R_ARM_TARGET1;
  189. case MCSymbolRefExpr::VK_ARM_TARGET2:
  190. return ELF::R_ARM_TARGET2;
  191. case MCSymbolRefExpr::VK_ARM_PREL31:
  192. return ELF::R_ARM_PREL31;
  193. case MCSymbolRefExpr::VK_ARM_SBREL:
  194. return ELF::R_ARM_SBREL32;
  195. case MCSymbolRefExpr::VK_ARM_TLSLDO:
  196. return ELF::R_ARM_TLS_LDO32;
  197. case MCSymbolRefExpr::VK_TLSCALL:
  198. return ELF::R_ARM_TLS_CALL;
  199. case MCSymbolRefExpr::VK_TLSDESC:
  200. return ELF::R_ARM_TLS_GOTDESC;
  201. case MCSymbolRefExpr::VK_TLSLDM:
  202. return ELF::R_ARM_TLS_LDM32;
  203. case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
  204. return ELF::R_ARM_TLS_DESCSEQ;
  205. }
  206. case ARM::fixup_arm_condbranch:
  207. case ARM::fixup_arm_uncondbranch:
  208. return ELF::R_ARM_JUMP24;
  209. case ARM::fixup_arm_movt_hi16:
  210. switch (Modifier) {
  211. default:
  212. Ctx.reportError(Fixup.getLoc(), "invalid fixup for ARM MOVT instruction");
  213. return ELF::R_ARM_NONE;
  214. case MCSymbolRefExpr::VK_None:
  215. return ELF::R_ARM_MOVT_ABS;
  216. case MCSymbolRefExpr::VK_ARM_SBREL:
  217. return ELF::R_ARM_MOVT_BREL;
  218. }
  219. case ARM::fixup_arm_movw_lo16:
  220. switch (Modifier) {
  221. default:
  222. Ctx.reportError(Fixup.getLoc(), "invalid fixup for ARM MOVW instruction");
  223. return ELF::R_ARM_NONE;
  224. case MCSymbolRefExpr::VK_None:
  225. return ELF::R_ARM_MOVW_ABS_NC;
  226. case MCSymbolRefExpr::VK_ARM_SBREL:
  227. return ELF::R_ARM_MOVW_BREL_NC;
  228. }
  229. case ARM::fixup_t2_movt_hi16:
  230. switch (Modifier) {
  231. default:
  232. Ctx.reportError(Fixup.getLoc(),
  233. "invalid fixup for Thumb MOVT instruction");
  234. return ELF::R_ARM_NONE;
  235. case MCSymbolRefExpr::VK_None:
  236. return ELF::R_ARM_THM_MOVT_ABS;
  237. case MCSymbolRefExpr::VK_ARM_SBREL:
  238. return ELF::R_ARM_THM_MOVT_BREL;
  239. }
  240. case ARM::fixup_t2_movw_lo16:
  241. switch (Modifier) {
  242. default:
  243. Ctx.reportError(Fixup.getLoc(),
  244. "invalid fixup for Thumb MOVW instruction");
  245. return ELF::R_ARM_NONE;
  246. case MCSymbolRefExpr::VK_None:
  247. return ELF::R_ARM_THM_MOVW_ABS_NC;
  248. case MCSymbolRefExpr::VK_ARM_SBREL:
  249. return ELF::R_ARM_THM_MOVW_BREL_NC;
  250. }
  251. }
  252. }
  253. void ARMELFObjectWriter::addTargetSectionFlags(MCContext &Ctx,
  254. MCSectionELF &Sec) {
  255. // The mix of execute-only and non-execute-only at link time is
  256. // non-execute-only. To avoid the empty implicitly created .text
  257. // section from making the whole .text section non-execute-only, we
  258. // mark it execute-only if it is empty and there is at least one
  259. // execute-only section in the object.
  260. MCSectionELF *TextSection =
  261. static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection());
  262. if (Sec.getKind().isExecuteOnly() && !TextSection->hasInstructions()) {
  263. for (auto &F : TextSection->getFragmentList())
  264. if (auto *DF = dyn_cast<MCDataFragment>(&F))
  265. if (!DF->getContents().empty())
  266. return;
  267. TextSection->setFlags(TextSection->getFlags() | ELF::SHF_ARM_PURECODE);
  268. }
  269. }
  270. std::unique_ptr<MCObjectTargetWriter>
  271. llvm::createARMELFObjectWriter(uint8_t OSABI) {
  272. return std::make_unique<ARMELFObjectWriter>(OSABI);
  273. }