RuntimeDyldELFMips.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. //===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===//
  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 "RuntimeDyldELFMips.h"
  9. #include "llvm/BinaryFormat/ELF.h"
  10. #define DEBUG_TYPE "dyld"
  11. void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE,
  12. uint64_t Value) {
  13. const SectionEntry &Section = Sections[RE.SectionID];
  14. if (IsMipsO32ABI)
  15. resolveMIPSO32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend);
  16. else if (IsMipsN32ABI) {
  17. resolveMIPSN32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
  18. RE.SymOffset, RE.SectionID);
  19. } else if (IsMipsN64ABI)
  20. resolveMIPSN64Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
  21. RE.SymOffset, RE.SectionID);
  22. else
  23. llvm_unreachable("Mips ABI not handled");
  24. }
  25. uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,
  26. uint64_t Value,
  27. uint64_t Addend) {
  28. if (IsMipsN32ABI) {
  29. const SectionEntry &Section = Sections[RE.SectionID];
  30. Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType,
  31. Addend, RE.SymOffset, RE.SectionID);
  32. return Value;
  33. }
  34. llvm_unreachable("Not reachable");
  35. }
  36. void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE,
  37. uint64_t Value) {
  38. if (IsMipsN32ABI) {
  39. const SectionEntry &Section = Sections[RE.SectionID];
  40. applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value,
  41. RE.RelType);
  42. return;
  43. }
  44. llvm_unreachable("Not reachable");
  45. }
  46. int64_t
  47. RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section,
  48. uint64_t Offset, uint64_t Value,
  49. uint32_t Type) {
  50. LLVM_DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x"
  51. << format("%llx", Section.getAddressWithOffset(Offset))
  52. << " FinalAddress: 0x"
  53. << format("%llx", Section.getLoadAddressWithOffset(Offset))
  54. << " Value: 0x" << format("%llx", Value) << " Type: 0x"
  55. << format("%x", Type) << "\n");
  56. switch (Type) {
  57. default:
  58. llvm_unreachable("Unknown relocation type!");
  59. return Value;
  60. case ELF::R_MIPS_32:
  61. return Value;
  62. case ELF::R_MIPS_26:
  63. return Value >> 2;
  64. case ELF::R_MIPS_HI16:
  65. // Get the higher 16-bits. Also add 1 if bit 15 is 1.
  66. return (Value + 0x8000) >> 16;
  67. case ELF::R_MIPS_LO16:
  68. return Value;
  69. case ELF::R_MIPS_PC32: {
  70. uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  71. return Value - FinalAddress;
  72. }
  73. case ELF::R_MIPS_PC16: {
  74. uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  75. return (Value - FinalAddress) >> 2;
  76. }
  77. case ELF::R_MIPS_PC19_S2: {
  78. uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  79. return (Value - (FinalAddress & ~0x3)) >> 2;
  80. }
  81. case ELF::R_MIPS_PC21_S2: {
  82. uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  83. return (Value - FinalAddress) >> 2;
  84. }
  85. case ELF::R_MIPS_PC26_S2: {
  86. uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  87. return (Value - FinalAddress) >> 2;
  88. }
  89. case ELF::R_MIPS_PCHI16: {
  90. uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  91. return (Value - FinalAddress + 0x8000) >> 16;
  92. }
  93. case ELF::R_MIPS_PCLO16: {
  94. uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  95. return Value - FinalAddress;
  96. }
  97. }
  98. }
  99. int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
  100. const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
  101. int64_t Addend, uint64_t SymOffset, SID SectionID) {
  102. LLVM_DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x"
  103. << format("%llx", Section.getAddressWithOffset(Offset))
  104. << " FinalAddress: 0x"
  105. << format("%llx", Section.getLoadAddressWithOffset(Offset))
  106. << " Value: 0x" << format("%llx", Value) << " Type: 0x"
  107. << format("%x", Type) << " Addend: 0x"
  108. << format("%llx", Addend)
  109. << " Offset: " << format("%llx" PRIx64, Offset)
  110. << " SID: " << format("%d", SectionID)
  111. << " SymOffset: " << format("%x", SymOffset) << "\n");
  112. switch (Type) {
  113. default:
  114. llvm_unreachable("Not implemented relocation type!");
  115. break;
  116. case ELF::R_MIPS_JALR:
  117. case ELF::R_MIPS_NONE:
  118. break;
  119. case ELF::R_MIPS_32:
  120. case ELF::R_MIPS_64:
  121. return Value + Addend;
  122. case ELF::R_MIPS_26:
  123. return ((Value + Addend) >> 2) & 0x3ffffff;
  124. case ELF::R_MIPS_GPREL16: {
  125. uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
  126. return Value + Addend - (GOTAddr + 0x7ff0);
  127. }
  128. case ELF::R_MIPS_SUB:
  129. return Value - Addend;
  130. case ELF::R_MIPS_HI16:
  131. // Get the higher 16-bits. Also add 1 if bit 15 is 1.
  132. return ((Value + Addend + 0x8000) >> 16) & 0xffff;
  133. case ELF::R_MIPS_LO16:
  134. return (Value + Addend) & 0xffff;
  135. case ELF::R_MIPS_HIGHER:
  136. return ((Value + Addend + 0x80008000) >> 32) & 0xffff;
  137. case ELF::R_MIPS_HIGHEST:
  138. return ((Value + Addend + 0x800080008000) >> 48) & 0xffff;
  139. case ELF::R_MIPS_CALL16:
  140. case ELF::R_MIPS_GOT_DISP:
  141. case ELF::R_MIPS_GOT_PAGE: {
  142. uint8_t *LocalGOTAddr =
  143. getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset;
  144. uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize());
  145. Value += Addend;
  146. if (Type == ELF::R_MIPS_GOT_PAGE)
  147. Value = (Value + 0x8000) & ~0xffff;
  148. if (GOTEntry)
  149. assert(GOTEntry == Value &&
  150. "GOT entry has two different addresses.");
  151. else
  152. writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());
  153. return (SymOffset - 0x7ff0) & 0xffff;
  154. }
  155. case ELF::R_MIPS_GOT_OFST: {
  156. int64_t page = (Value + Addend + 0x8000) & ~0xffff;
  157. return (Value + Addend - page) & 0xffff;
  158. }
  159. case ELF::R_MIPS_GPREL32: {
  160. uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
  161. return Value + Addend - (GOTAddr + 0x7ff0);
  162. }
  163. case ELF::R_MIPS_PC16: {
  164. uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  165. return ((Value + Addend - FinalAddress) >> 2) & 0xffff;
  166. }
  167. case ELF::R_MIPS_PC32: {
  168. uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  169. return Value + Addend - FinalAddress;
  170. }
  171. case ELF::R_MIPS_PC18_S3: {
  172. uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  173. return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;
  174. }
  175. case ELF::R_MIPS_PC19_S2: {
  176. uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  177. return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;
  178. }
  179. case ELF::R_MIPS_PC21_S2: {
  180. uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  181. return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;
  182. }
  183. case ELF::R_MIPS_PC26_S2: {
  184. uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  185. return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;
  186. }
  187. case ELF::R_MIPS_PCHI16: {
  188. uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  189. return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;
  190. }
  191. case ELF::R_MIPS_PCLO16: {
  192. uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
  193. return (Value + Addend - FinalAddress) & 0xffff;
  194. }
  195. }
  196. return 0;
  197. }
  198. void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,
  199. uint32_t Type) {
  200. uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
  201. switch (Type) {
  202. default:
  203. llvm_unreachable("Unknown relocation type!");
  204. break;
  205. case ELF::R_MIPS_GPREL16:
  206. case ELF::R_MIPS_HI16:
  207. case ELF::R_MIPS_LO16:
  208. case ELF::R_MIPS_HIGHER:
  209. case ELF::R_MIPS_HIGHEST:
  210. case ELF::R_MIPS_PC16:
  211. case ELF::R_MIPS_PCHI16:
  212. case ELF::R_MIPS_PCLO16:
  213. case ELF::R_MIPS_CALL16:
  214. case ELF::R_MIPS_GOT_DISP:
  215. case ELF::R_MIPS_GOT_PAGE:
  216. case ELF::R_MIPS_GOT_OFST:
  217. Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff);
  218. writeBytesUnaligned(Insn, TargetPtr, 4);
  219. break;
  220. case ELF::R_MIPS_PC18_S3:
  221. Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);
  222. writeBytesUnaligned(Insn, TargetPtr, 4);
  223. break;
  224. case ELF::R_MIPS_PC19_S2:
  225. Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);
  226. writeBytesUnaligned(Insn, TargetPtr, 4);
  227. break;
  228. case ELF::R_MIPS_PC21_S2:
  229. Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);
  230. writeBytesUnaligned(Insn, TargetPtr, 4);
  231. break;
  232. case ELF::R_MIPS_26:
  233. case ELF::R_MIPS_PC26_S2:
  234. Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);
  235. writeBytesUnaligned(Insn, TargetPtr, 4);
  236. break;
  237. case ELF::R_MIPS_32:
  238. case ELF::R_MIPS_GPREL32:
  239. case ELF::R_MIPS_PC32:
  240. writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);
  241. break;
  242. case ELF::R_MIPS_64:
  243. case ELF::R_MIPS_SUB:
  244. writeBytesUnaligned(Value, TargetPtr, 8);
  245. break;
  246. }
  247. }
  248. void RuntimeDyldELFMips::resolveMIPSN32Relocation(
  249. const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
  250. int64_t Addend, uint64_t SymOffset, SID SectionID) {
  251. int64_t CalculatedValue = evaluateMIPS64Relocation(
  252. Section, Offset, Value, Type, Addend, SymOffset, SectionID);
  253. applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
  254. Type);
  255. }
  256. void RuntimeDyldELFMips::resolveMIPSN64Relocation(
  257. const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
  258. int64_t Addend, uint64_t SymOffset, SID SectionID) {
  259. uint32_t r_type = Type & 0xff;
  260. uint32_t r_type2 = (Type >> 8) & 0xff;
  261. uint32_t r_type3 = (Type >> 16) & 0xff;
  262. // RelType is used to keep information for which relocation type we are
  263. // applying relocation.
  264. uint32_t RelType = r_type;
  265. int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value,
  266. RelType, Addend,
  267. SymOffset, SectionID);
  268. if (r_type2 != ELF::R_MIPS_NONE) {
  269. RelType = r_type2;
  270. CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
  271. CalculatedValue, SymOffset,
  272. SectionID);
  273. }
  274. if (r_type3 != ELF::R_MIPS_NONE) {
  275. RelType = r_type3;
  276. CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
  277. CalculatedValue, SymOffset,
  278. SectionID);
  279. }
  280. applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
  281. RelType);
  282. }
  283. void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section,
  284. uint64_t Offset,
  285. uint32_t Value, uint32_t Type,
  286. int32_t Addend) {
  287. uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);
  288. Value += Addend;
  289. LLVM_DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: "
  290. << Section.getAddressWithOffset(Offset) << " FinalAddress: "
  291. << format("%p", Section.getLoadAddressWithOffset(Offset))
  292. << " Value: " << format("%x", Value) << " Type: "
  293. << format("%x", Type) << " Addend: " << format("%x", Addend)
  294. << " SymOffset: " << format("%x", Offset) << "\n");
  295. Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
  296. applyMIPSRelocation(TargetPtr, Value, Type);
  297. }